一、Java中支持的位運算
- 位與(&):二元運算符,兩個為1時結果為1,否則為0
- 位或(|):二元運算符,兩個其中有一個為1時結果就為1,否則為0
- 位異或(^):二元運算符,兩個數同時為1或0時結果為1,否則為0
- 位取非(~):一元運算符,取反操作
- 左移(<<):一元運算符,按位左移一定的位置。高位溢出,低位補符號位,符號位不變。
- 右移(>>):一元運算符,按位右移一定的位置。高位補符號位,符號位不變,低位溢出。
- 無符號右移(>>>):一元運算符,符號位(即最高位)保留,其它位置向右移動,高位補零,低位溢出。
二、位運算規則
Java數值運算過程中都是先將十進制轉換為二進制然后再進行運算,再把二進制數據轉換為十進制展現給用戶。二進制運算規則如下:
對於有符號的而言,
- 最高位為符號位,0表示正數,1表示負數
- 正數的原碼,反碼和補碼都一樣,三碼合一
- 負數的反碼:符號位保持不限,其他位取反
- 負數的補碼:補碼 + 1
- 0的反碼和補碼都是0
- 計算機的運算的時候,都是將原碼轉成補碼進行運算的
下面以 -1 為例子展示原碼、反碼和補碼的轉換關系(以int數據類型為例,int類型在Java中占4字節):
三、邏輯運算
(一)、與運算(&)
一、運算規則
兩個數相同位置的比特進行與運算,若兩個位置均為1,那么結果就為1,否者為0。
二、運算流程
以 4 & -5 = 0為例子展示運算流程:
1. 因為4為正數,所以原碼和補碼相同,即4的補碼為:00000000 0000000 00000000 00000100
2.因為-5為負數,所以需要進行原碼 >>> 反碼 >>> 補碼的轉換
1)原碼:10000000 00000000 00000000 00000101
2)反碼:11111111 11111111 11111111 11111010
3)補碼:11111111 11111111 11111111 11111011
3.將4和-5的補碼進行 & 運算:00000000 0000000 00000000 00000100
11111111 11111111 11111111 11111011 &
00000000 00000000 00000000 00000000
4.得到的補碼結果為:00000000 00000000 00000000 00000000。所以結果為0
(二)、或運算(|)
一、運算規則
兩個數相同位置的比特進行或運算,若其中一個為1則結果為1,否個結果為0。
二、運算流程
以 -2 | 5 = -1為例展示運算流程:
1.-2為負數,需要進行原碼 > 反碼 > 補碼的轉換。轉換步驟如下:
1)原碼:10000000 00000000 00000000 00000010
2)符號位不變,其他位置取反得反碼:11111111 11111111 11111111 11111101
3)在反碼的基礎上+1得到補碼: 11111111 11111111 11111111 11111110
2.5為正數,補碼和反碼一致,所以5的補碼為:00000000 00000000 00000000 00000101
3.將-2 和 5 的補碼進行或運算: 11111111 11111111 11111111 11111110
| 00000000 00000000 00000000 00000101
11111111 11111111 11111111 11111111
4.根據上面的運算得到補碼結果為:11111111 11111111 11111111 11111111
5.結果顯然是一個負數,而負數的補碼和原碼不一致,所以需要將補碼結果轉換為原碼才能得到最終的結果
6.補碼轉原碼的過程是跟原碼轉補碼相反的過程,具體過程如下:
1)補碼:11111111 11111111 11111111 11111111
2)補碼 -1 得到反碼:11111111 11111111 11111111 11111110
3)符號位不變,其他位置取反得:10000000 00000000 00000000 00000001
7.最終得到的原碼結果為 10000000 00000000 00000000 00000001,轉成十進制為 -1
(三)、異或運算(^)
一、運算規則
兩個數相同位置的比特進行或運算,若兩個數均為0或1,則結果為0,否者為1.
二、運算流程
以 1 ^ -5 = 6 為例,具體運算流程如下:
1.1的補碼為:00000000 00000000 00000000 00000001
2.-5的補碼為:11111111 11111111 11111111 11111011(可參考與運算給出的流程)
3.兩個補碼運算:
00000000 00000000 00000000 00000001
^ 11111111 11111111 11111111 11111011
11111111 11111111 11111111 11111010
4.得到的補碼結果為:11111111 11111111 11111111 11111010
5.補碼為負數,需要轉換成原碼:
1)補碼:11111111 11111111 11111111 11111010
2)反碼:11111111 11111111 11111111 11111001
3)原碼:10000000 00000000 00000000 000000110
6.由原碼:10000000 00000000 00000000 000000110,得出最終的時間結果為 -6.
(四)、取反運算(~)
一、運算規則
若位數為0,則取反后為1,若為1,取反后為0。
二、運算規則
以~2 = -3為例運算流程如下:
1.2的原碼為:00000000 00000000 00000000 00000010
2.2的補碼跟原碼一致也為:00000000 00000000 00000000 00000010
3.取反:111111111 11111111 11111111 11111101
4.取反后的結果仍未補碼,此時補碼為負數,則需要轉成原碼
5. 11111111 11111111 11111111 11111101 - 1 得到反碼:11111111 11111111 11111111 11111100
6. 11111111 11111111 11111111 11111100 符號位不變,其他位置取反得到原碼為:10000000 00000000 00000000 00000011
7. 10000000 00000000 00000000 00000011 轉成十進制結果為 -3
四、位移操作
(一)、左移(<<)
規則:符號位不變,高位溢出截斷,低位補零。比如 -1 << 2 = -4 (為方便講解,圖示的補碼為-1)
(二)、右移(>>)
規則:符號位不變,低位溢出截斷,高位用符號位填充。如:8 >> 2 = 2。
(三)、無符號右移(>>>)
規則:高位填充0,低位溢出。如-1>>>1=2147483647