Câu trả lời:
>>
là dịch chuyển số học đúng, >>>
là dịch chuyển logic phải.
Trong một sự thay đổi số học, bit dấu được mở rộng để duy trì độ ký của số.
Ví dụ: -2 được biểu thị bằng 8 bit sẽ là 11111110
(vì bit quan trọng nhất có trọng số âm). Thay đổi đúng một bit bằng cách sử dụng dịch chuyển số học sẽ cung cấp cho bạn 11111111
hoặc -1. Tuy nhiên, sự thay đổi hợp lý không quan tâm rằng giá trị có thể đại diện cho một số đã ký; nó chỉ đơn giản là di chuyển mọi thứ sang bên phải và điền vào từ bên trái với 0s. Thay đổi -2 đúng một bit của chúng tôi bằng cách sử dụng dịch chuyển logic sẽ cung cấp 01111111
.
2^k
, tôi thấy thật kỳ lạ khi đây là câu trả lời của mọi người. Một chuỗi bit không phải là số và >>
luôn có thể được sử dụng trên bất kỳ chuỗi bit nào: nó luôn luôn làm điều tương tự bất kể vai trò của chuỗi bit đó là gì và bất kể nó có khái niệm 'dấu' hay không. Có thể mở rộng câu trả lời tuyệt vời của bạn bằng một cuộc thảo luận về trường hợp khi toán hạng của bạn không được hiểu là một số đã ký? Liệu khiếu nại của tôi có ý nghĩa?
String
cũng có thể được coi là a char[]
. Anh ta không nói rằng đó char
không phải là một con số; Anh ta chỉ nói rằng đó là một con số không dấu . Tôi nghĩ đó là nơi anh ấy đã mất.
>>>
là dịch chuyển không dấu; nó sẽ chèn 0. >>
được ký và sẽ mở rộng bit dấu.
Các toán tử thay đổi bao gồm dịch chuyển trái
<<
, dịch chuyển phải ký>>
và dịch chuyển phải không dấu>>>
.Giá trị của
n>>s
làn
cács
vị trí bit dịch chuyển phải với phần mở rộng dấu hiệu .Giá trị của
n>>>s
làn
cács
vị trí bit dịch chuyển phải với phần mở rộng bằng không .
System.out.println(Integer.toBinaryString(-1));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >> 16));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >>> 16));
// prints "1111111111111111"
Để làm cho mọi thứ rõ ràng hơn thêm đối tác tích cực
System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"
Vì nó là dương cả ca làm việc có dấu và không dấu sẽ thêm 0 vào hầu hết bit.
1 >>> 32 == 1
Cả hai đều chuyển đúng, nhưng >>>
làunsigned
Từ tài liệu :
Toán tử dịch chuyển phải không dấu ">>>" chuyển số 0 sang vị trí ngoài cùng bên trái, trong khi vị trí ngoài cùng bên trái sau ">>" phụ thuộc vào phần mở rộng dấu hiệu.
>>>
là không dấu, nhưng tại sao 7>>32=7
? Tôi đã chạy một vòng lặp làm một ca tại một thời điểm và thấy rằng sau khi 32
thay đổi, nó đã quay trở lại 7
. Cách duy nhất mà điều này có thể có ý nghĩa là với mỗi số được chuyển ra, nó đã nhập vào một "vòng tròn bên ngoài". Sau khi 32
thay đổi, nó đạt được bằng cách nào đó trở lại vị trí của nó, nhưng rõ ràng điều đó vẫn không có ý nghĩa. Chuyện gì đang xảy ra vậy?
Sự dịch chuyển logic phải ( v >>> n
) trả về một giá trị trong đó các bit trong v
đã được dịch chuyển sang phải theo n
vị trí bit và 0 được dịch chuyển từ phía bên trái. Xem xét thay đổi giá trị 8 bit, được viết dưới dạng nhị phân:
01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000
Nếu chúng ta hiểu các bit là một số nguyên không dấu không dấu, sự dịch chuyển logic phải có tác dụng chia số cho công suất tương ứng là 2. Tuy nhiên, nếu số đó nằm trong biểu diễn bổ sung của hai, thì dịch chuyển logic phải không phân chia chính xác các số âm . Ví dụ, sự dịch chuyển bên phải thứ hai ở trên thay đổi 128 đến 32 khi các bit được hiểu là số không dấu. Nhưng nó thay đổi -128 thành 32 khi, như điển hình trong Java, các bit được diễn giải theo hai phần bù.
Do đó, nếu bạn đang dịch chuyển để chia cho lũy thừa hai, bạn muốn dịch chuyển đúng số học ( v >> n
). Nó trả về một giá trị trong đó các bit trong v
đã được dịch chuyển sang phải theo n
vị trí bit và các bản sao của bit ngoài cùng bên trái của v được dịch chuyển từ phía bên trái:
01111111 >> 2 = 00011111
10000000 >> 2 = 11100000
Khi các bit là một số trong biểu diễn bổ sung của hai, sự dịch chuyển phải của số học có tác dụng chia cho lũy thừa của hai. Điều này hoạt động vì bit ngoài cùng bên trái là bit dấu. Chia cho một sức mạnh của hai phải giữ dấu hiệu như nhau.
Đọc thêm về Toán tử Bitwise và Bit Shift
>> Signed right shift
>>> Unsigned right shift
Mẫu bit được đưa ra bởi toán hạng bên trái và số lượng vị trí để thay đổi bởi toán hạng bên phải. Các nhà điều hành dịch phải unsigned >>>
chuyển một zero vào vị trí tận cùng bên trái ,
trong khi vị trí ngoài cùng bên trái sau >>
phụ thuộc vào dấu hiệu mở rộng.
Nói một cách đơn giản, >>>
luôn luôn chuyển số 0 sang vị trí ngoài cùng bên trái trong khi >>
dịch chuyển dựa trên dấu của số tức là 1 cho số âm và 0 cho số dương.
Ví dụ thử với số âm cũng như số dương.
int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));
System.out.println();
c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
đầu ra:
11111111111111111111111111011001
11111111111111111111111101100100
111111111111111111111111011001
11111111111111111111111101100100
100110
10011000
100110
10011000
System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0'))
; Số nguyên.MAX_VALUE : Số 01111111111111111111111111111111;
nguyên.MIN_VALUE : 10000000000000000000000000000000;
-1 : 11111111111111111111111111111111;
0 : 00000000000000000000000000000000;
1 : 00000000000000000000000000000001
Toán tử logic dịch chuyển phải ( >>> N
) dịch chuyển bit sang phải theo vị trí N, loại bỏ bit dấu và đệm N bit trái nhất với 0 '. Ví dụ:
-1 (in 32-bit): 11111111111111111111111111111111
sau khi >>> 1
hoạt động trở thành:
2147483647: 01111111111111111111111111111111
Toán tử số học dịch chuyển phải ( >> N
) cũng dịch chuyển các bit sang phải theo các vị trí N, nhưng vẫn giữ bit dấu và đệm N bit trái nhất với 1 bit. Ví dụ:
-2 (in 32-bit): 11111111111111111111111111111110
sau khi >> 1
hoạt động trở thành:
-1: 11111111111111111111111111111111