1. 無符號右移 >>> 或 >>> =
無符號右移(>>>)跟右移(>>)運算符不一樣。
右移不改變數的正負。
對於一個正數,無符號右移不會變成負數(相當於除以1再取整);但是對於一個負數,無符號右移會將負數變成正數;
int i = -4;
System.out.printf("%-10d %32s\n", i, Integer.toBinaryString(i));
i >>>= 1; // 無符號右移1位
System.out.printf("%-10d %32s\n", i, Integer.toBinaryString(i));
i >>>= 1;
System.out.printf("%-10d %32s\n", i, Integer.toBinaryString(i));
輸出:
-4 11111111111111111111111111111100 //負數在java中以補碼形式存儲,-4的補碼表示是11111111111111111111111111111100
2147483646 1111111111111111111111111111110 //無符號右移1位,-4的補碼表示的符號位也右移了1位,導致符號位變成0,成為正數
1073741822 111111111111111111111111111110 //再無符號右移1位
int i = 15; System.out.printf("%-10d %32s\n", i, Integer.toBinaryString(i)); i >>>= 1; System.out.printf("%-10d %32s\n", i, Integer.toBinaryString(i));
輸出:
15 1111
7 111 //對正數進行無符號右移,高位補0
int i = 0x80000000; System.out.printf("%-12d %32s\n", i, Integer.toBinaryString(i)); i >>>= 1; System.out.printf("%-12d %32s\n", i, Integer.toBinaryString(i)); i >>>= 1; System.out.printf("%-12d %32s\n", i, Integer.toBinaryString(i));
輸出:
-2147483648 10000000000000000000000000000000 //最小負數的補碼表示
1073741824 1000000000000000000000000000000 //符號位右移一位,變成正數
536870912 100000000000000000000000000000
總結:
無符號右移的叫法,容易讓人誤解。雖然叫作無符號右移運算,讓人第一印象以為是不對符號位進行移位,其實卻是連同符號位一起右移;
對復數進行無符號右移,符號位也一起右移,將會變成正數;
對正數進行若干次無符號右移,得到的永遠都是正數或0;
2. 左移位運算 << 或 <<=
跟右移運算不同的是,無符號左移和左移是一樣的。因此java沒有無符號左移運算。(<<<和<<<=將報錯)
因為無右移運算需要考慮符號位的右移,而符號位只存在於二進制表示的最左邊,最右邊沒有。
所以不用區分無符號左移和左移運算。
int i = 0x80000000; System.out.printf("%-12d %32s\n", i, Integer.toBinaryString(i)); i <<= 1; System.out.printf("%-12d %32s\n", i, Integer.toBinaryString(i)); i >>= 1; System.out.printf("%-12d %32s\n", i, Integer.toBinaryString(i));
輸出:
-2147483648 10000000000000000000000000000000
0 0 //最小負數左移1位,將變成0
0 0