Sự khác biệt giữa >>> và >>


Câu trả lời:


408

>>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 11111111hoặ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.


8
Mặc dù tôi đồng ý và đánh giá cao rằng các thay đổi số học có thể được sử dụng để nhân các số đã ký bằng 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?
Ziggy

11
Tại sao bạn nói một chuỗi bit không phải là số? Bạn có thể nói một chuỗi các chữ số thập phân không phải là một số?
danben

4
@danben Thảo luận về việc đó có phải hay không một con số chỉ có ý nghĩa nếu bạn liên kết nó với một bối cảnh. Nếu internet chỉ là điện, thì tôi đồng ý rằng Chuỗi chỉ là một số.
bvdb

1
@danben nhưng thực ra, tôi nghĩ những gì Ziggy thực sự đề cập đến (imho), đó là a Stringcũng có thể được coi là a char[]. Anh ta không nói rằng đó charkhô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.
bvdb

5
@Ziggy là đúng: Không phải mọi chuỗi bit là một số và không phải mọi chuỗi số thập phân là một số. Ví dụ: Số điện thoại, mã bưu điện (ở nhiều quốc gia), v.v. là các chuỗi chữ số thập phân, nhưng không có nghĩa gì để thêm, trừ hoặc nhân chúng, vì vậy chúng không thực sự là số. Chúng là các chuỗi các chữ số thập phân, nhưng nên được coi là các chuỗi ký tự. (Mã bưu điện ở Canada và Vương quốc Anh có chứa các chữ cái và chữ số.)
jcsahnwaldt nói GoFundMonica

102

>>>là dịch chuyển không dấu; nó sẽ chèn 0. >>được ký và sẽ mở rộng bit dấu.

Toán tử thay đổi JLS 15.19

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>>sncác svị trí bit dịch chuyển phải với phần mở rộng dấu hiệu .

Giá trị của n>>>sncác svị 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.

Câu hỏi liên quan


Không có ví dụ của bạn, tôi sẽ không nhận được nó.
mr5

47

Cả hai đều chuyển đúng, nhưng >>>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.


12
bạn có thể giải thích với một ví dụ
Kasun Siyambalapitiya

1
Tôi cũng nghĩ bạn nên đưa ra một ví dụ.
byxor 6/12/2016

Tôi cho rằng đó >>>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 32thay đổ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 32thay đổ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?
Ian Limarta

@IanLimarta Nó không? Tôi chỉ nhận được 0. ( for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));) Nếu bạn có nghĩa là tại sao >>32chính nó trả về giá trị ban đầu, hãy xem điều này .
Moira

Tôi xin lỗi. Ý tôi là tại sao '7 >>> 32 = 7'.
Ian Limarta

40

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 nvị 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 nvị 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.


38

>>>sẽ luôn đặt 0 ở bên trái hầu hết các bit, trong khi >>sẽ đặt 1 hoặc 0 tùy thuộc vào dấu hiệu của nó là gì.


10

Đọ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

Cảm ơn. Chỉ muốn thêm một nhận xét để tham chiếu biểu diễn bit cho Integer.MAX_VALUE, Integer.MIN_VALUE, -1, 0, 1 . ví dụ : 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
Andy Dong

6

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 >>> 1hoạ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 >> 1hoạt động trở thành:

-1: 11111111111111111111111111111111
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.