Để ý rằng:
- nếu
x
có bit thứ n-1
là 0, thì tất cả những bit cao hơn nó phải là 0 hết thì x
mới fit được trong n
bits.
- nếu
x
có bit thứ n-1
là 1, thì tất cả những bit cao hơn nó phải là 1 hết thì x
mới fit được trong n
bits.
Vậy bài toán chuyển về kiểm tra các bit thứ n, n+1, … có giống với bit thứ n-1 hết hay ko.
2 cái để ý này hơi khó thấy ngay được nếu em mới học, thử viết vài số âm/dương thành dạng 2’s complement với số bit khác nhau sẽ thấy. Ví dụ:
- 17 = (0010010) biểu diễn với 7 bit, nếu biểu diễn với 3 bit (0010010) sẽ ko đủ vì có số 1 phía trước bit 0 thứ 2 (thứ 0 là bit đầu tiên bên phải)
- 2 = (0000010) biểu diễn với 7 bit, nếu biểu diễn với 3 bit (0000010) sẽ đủ vì các bit cao hơn bit thứ 2 đều có giá trị là 0 giống với bit thứ 2.
- -36 = (1011100) biểu diễn với 7 bit, nếu biểu diễn với 3 bit (1011100) sẽ ko đủ vì có số 1 phía trước bit 0 thứ 2
- -3 = (1111101) biểu diễn với 7 bit, nếu biểu diễn với 3 bit (1111101) sẽ đủ vì các bit cao hơn bit thứ 2 đều có giá trị là 1 giống với bit thứ 2.
Cho số b31b30b29…bnbn-1bn-2…b2b1b0 ta cần tạo ra số mới bn-1bn-1bn-1…bn-1bn-1bn-2…b2b1b0, rồi đem số mới này XOR với số cho trước, để kiểm tra xem 2 số có giống nhau hay ko, nếu giống thì trả về true. (a, b giống nhau thì a xor b trả về 0 nên phải thêm toán tử NOT nữa)
Muốn làm các bit đứng trước bn-1 giống bn-1 thì ta có thể shift left cho nó bay hết mấy bit trước nó, rồi shift right về lại vị trí cũ, hy vọng các bit mới điền vào chỗ trống giống với bit cao nhất lúc này là bit thứ n-1. Từ n tới 31 có 31 - n + 1 = 32 - n bit nên phải tính trước shift = 33 + ~n vì trong 2’s complement -n = ~n + 1 nên 32 - n = 32 + ~n + 1 = 33 + ~n.
- b31b30b29…bnbn-1bn-2…b2b1b0
<< (32-n)
hy vọng sẽ ra bn-1bn-2…b2b1b0a31-na30-n…a1a0 (ai có giá trị bao nhiêu ko cần biết vì tiếp theo nó sẽ bị xóa mất)
-
bn-1bn-2…b2b1b0a31-na30-n…a1a0
>> (32-n)
hy vọng sẽ ra bn-1bn-1bn-1…bn-1bn-1bn-2…b2b1b0
-
bn-1bn-1bn-1…bn-1bn-1bn-2…b2b1b0
^
b31b30b29…bnbn-1bn-2…b2b1b0 sẽ ra x31x30x29…xn00…000. Nếu các bit bên trái bit thứ n-1 giống với bn-1 hết thì kết quả sẽ ra 0, còn ko sẽ ra một số khác 0. Cuối cùng đem kết quả này apply toán tử NOT vào sẽ ra true nếu kết quả XOR==0, false nếu kết quả trước đó khác 0.
Vấn đề là trong C và C++, a << b với a có dấu và a < 0 là ko xác định =) Có thể compiler trường xài nó làm y hệt như trên, nhưng compiler khác nó ko làm như vậy cũng ko đốt compiler đó đc vì nó ko làm sai chuẩn vì chuẩn nói anh thích làm gì thì làm, vì dòng code này ko xác định. Nhưng có lẽ đa số là các compiler nó làm đúng như trên nên chắc ko sao :V