Java 位運算符
前言
最近在看hashMap的源碼,看到了一些位運算符,決定深入研究學習一下位運算符。
位運算
定義:程序中的所有數在計算機內存中都是以二進制的形式儲存的。位運算說穿了,就是直接對整數在內存中的二進制位進行操作。
位運算符
Java中的位運算符一共有:&、|、^ 、<<、>>、>>>、~這7種
1.&(與)、|(或)、^(異或)
public static void main(String[] args) { int a = 10; System.out.println("a的二進制表示:" + Integer.toBinaryString(a));int b = 11; System.out.println("b的二進制表示:" + Integer.toBinaryString(b)); int i = a & b; System.out.println("a & b = " + i + ",i的二進制表示:" + Integer.toBinaryString(i)); i = a | b; System.out.println("a | b = " + i + ",i的二進制表示:" + Integer.toBinaryString(i)); i= a ^ b; System.out.println("a ^ b = " + i + ",i的二進制表示:" + Integer.toBinaryString(i)); }
運行結果
a的二進制表示:1010 b的二進制表示:1011 a & b = 10,i的二進制表示:1010 a | b = 11,i的二進制表示:1011 a ^ b = 1,i的二進制表示:1
可以通過Java中Integer類自帶將int轉為二進制表示的方法查看二進制
這裏a ^ b 的二進制表示可以看成0001
可以看出
& (與):當a和b二進制表示上相同位數都為1時,i的對應位數上的值才為1(既11-->1 10 -->0 01-->0 00-->0),不難看出 i <= min(a,b)
| (或):當a和b二進制表示上相同位數都為0時,i的對應位數上的值才為0(既11-->1 10 -->1 01-->1 00-->0),不難看出 i >= max(a,b)
^(異或):當a和b二進制表示上相同位數相同時,i的對應位數上的紙值為0(既11-->0 10 -->1 01-->1 00-->0)
2. <<(左移)、>>(帶符號右移)、>>>(無符號右移)
public static void main(String[] args) { int i = 1 << 2; System.out.println("1 << 2 = " + i); i = 1 << 30; System.out.println("1 << 30 = " + i); i = 1 << 31; System.out.println("1 << 31 = " + i); i = 1 >> 1; System.out.println("1 >> 1 = " + i); i = 1 >> 32; System.out.println("1 >> 32 = " + i); i = -1 >> 1; System.out.println("-1 >> 1 = " + i); i = -1 >>> 1; System.out.println("-1 >>> 1 = " + i); }
運行結果
1 << 2 = 4 1 << 30 = 1073741824 1 << 31 = -2147483648 1 >> 1 = 0 1 >> 32 = 1 -1 >> 1 = -1 -1 >>> 1 = 2147483647
一般情況下
a << n = (a * (2的n次方 ))
a >> n=(a-a%2)/(2的n次方)
但是,可以看到上面的例子中可以列出不少返例
這其中主要因為Java中int的範圍
首先,Java中int的範圍是 -2的32次~2的32次-1
另外,我們有沒有考慮過i的邊界問題,當i = 2的32次-1後,再+1,會出現什麽後果?
public static void main(String[] args) {
int i = Integer.MAX_VALUE +1;
System.out.println(i);
System.out.println(Integer.toBinaryString(i));
}
運行結果
-2147483648(-2的32次方。int的最小值)
10000000000000000000000000000000
我們知道int的長度是32位的,要表示Int的正負,Java中的做法是在第32位上做標記,第32位=0時,int為正數,第32位=-1時,int為負數
所以
二進制:00000000000000000000000000000000 ,代表最小的正數0
二進制:10000000000000000000000000000000 ,代表最小的負數-2147483648
從二進制計算的角度不難理解,Integer.MAX_VALUE+1 = Integer.MIN_VALUE
這就是為什麽 1<<31 = -2147483648
我們再來看
1 >> 1 = 0 和 1 >> 32 = 1
這裏我理解為 二進制中移位運算實際是對一個長度為63的二進制數進行操作,其中連續的32位表示int的值,剩余部分全部為0。
然後再講這整個63位的二進制數看成一個圓(循環隊列)
所以,無論一個數左移或者右移32位,始終是這個數本身。
然後,我們來看一下 -1 >>1 = -1 和 -1>>>1 = 2147483647
先從字面上理解,>> 帶符號右移,>>>無符號右移
再進一步解釋就很容易了,63位長度的二進制數中,其中連續的32位表示int的值,剩余的31位再做>>操作時,保持與int的符號相同的值(即int位負,其余31位都為1,int為正,其余31位都為0)
而>>>無符號右移,則是無論int為何,其余31位全部為0
3.~(取反)
public static void main(String[] args) { int i = 10; System.out.println(Integer.toBinaryString(i)); System.out.println(Integer.toBinaryString(~i)); }
運行結果
1010 11111111111111111111111111110101
取反很容易理解,將0替換成1,將1替換成0
將10的二進制表示補充至完整的32位
00000000000000000000000000001010 取反則等於11111111111111111111111111110101
可以看出 i + ~i = -1
---------------------------------------------------------------------------------------------------------------------
第一次寫博客,很多地方都是個人理解,如果寫得不對的地方,請撥冗指正,謝謝!
Java 位運算符