Java提供的位運算符有:左移( << )、右移( >> ) 、無符号右移( >>> ) 、位與( & ) 、位或( | )、位非( ~ )、位異或( ^ ),除了位非( ~ )是一進制操作符外,其它的都是二進制操作符。
PS:所有的位運算操作都是基于二進制補碼進行的,幹開發的都應該知道相關知識吧,我就不多哔哔。
在移位運算時,byte、short和char類型移位後的結果會變成int類型,對于byte、short、char和int進行移位時,規定實際移動的次數是移動次數和32的餘數,也就是移位33次和移位1次得到的結果相同。移動long型的數值時,規定實際移動的次數是移動次數和64的餘數,也就是移動66次和移動2次得到的結果相同。
<<(左移)
按二進制形式把所有的數字向左移動對應的位數,高位移出(舍棄),低位的空位補零。
文法格式 需要移位的數字 << 移位的次數
例如:
System.out.println("'<<'位操作符(10 << 3):" + (10 << 3));
----------
輸出結果
80
首先把10轉換為二進制數字0000 0000 0000 0000 0000 0000 0000 1010,然後把該數字高位(左側)的兩個零移出,其他的數字都朝左平移2位,最後在低位(右側)的兩個空位補零。則得到的最終結果是0000 0000 0000 0000 0000 0000 0010 1000,則轉換為十進制是80.
數學意義
在數字沒有溢出的前提下,對于正數和負數,左移一位都相當于乘以2的1次方,左移n位就相當于乘以2的n次方。 即:10*2^3=80
>>(右移)
按二進制形式把所有的數字向右移動對應val位數,低位移出(舍棄),高位的空位補符号位,即正數補零,負數補1.
文法格式 需要移位的數字 >> 移位的次數
例如
System.out.println("'>>'位操作符(10 >> 3):" + (10 >> 3));
System.out.println("'>>'位操作符(-10 >> 3):" + (-10 >> 3));
---------- 輸出結果
'>>'位操作符(10 >> 3):1
'>>'位操作符(-10 >> 3):-2
10的二進制形式為:0000 0000 0000 0000 0000 0000 0000 1010,然後把低位的最後兩個數字移出,因為該數字是正數,是以在高位補零。則得到的最終結果是0000 0000 0000 0000 0000 0000 0000 0001.轉換為十進制是1.即:10/2^3 取整 1
數學意義 右移一位相當于除2,右移n位相當于除以2的n次方。
>>>(無符号右移)
按二進制形式把所有的數字向右移動對應val位數,低位移出(舍棄),高位的空位補零。對于正數來說和帶符号右移相同,對于負數來說不同。
System.out.println("'>>>'位操作符(-10 >>> 3):" + (-10 >>> 3));
System.out.println("'>>>'位操作符(10 >>> 3):" + (10 >>> 3));
------------ 輸出結果:
'>>>'位操作符(-10 >>> 3):536870910
'>>>'位操作符(10 >>> 3):1
對-10右移三位的過程為:舍棄二進制數的最後三位,在二進制數的開頭增加三個0,導緻原來的符号位由‘1’變成了‘0’,由負數變成了正數;
-10的二進制原碼: 1000 0000 0000 0000 0000 0000 0000 1010,
反碼:1111 1111 1111 1111 1111 1111 1111 0101
補碼:1111 1111 1111 1111 1111 1111 1111 0110
補碼右移三位後 0001 1111 1111 1111 1111 1111 1111 1110,轉換成十進制 536870910
& (與運算符)
與運算時,進行運算的兩個數,從最低位到最高位,一一對應。如果某 bit 的兩個數值對應的值都是 1,則結果值相應的 bit 就是 1,否則為 0.
0 & 0 = 0,
0 & 1 = 0,
1 & 1 = 1
System.out.println("'&'位操作符(10 & 3):" + (10 & 3));
---------
輸出結果:
'&'位操作符(10 & 3):2
|(或運算符)
與運算時,進行運算的兩個數,從最低位到最高位,一一對應。如果某 bit 的兩個數值對應的值隻要 1 個為 1,則結果值相應的 bit 就是 1,否則為 0。
0 | 0 = 0,
0 | 1 = 1,
1 | 1 = 1
System.out.println("'|'位操作符(10 | 3):" + (10 | 3));
----------
輸出結果:
'|'位操作符(10 | 3):11
~ (取反運算符)
對操作數的每一位進行操作,1 變成 0,0 變成 1。
System.out.println("'~'位操作符(~ 10):" + (~10));
System.out.println("'~'位操作符(~ -10):" + (~-10));
----------
輸出結果:
'~'位操作符(~ 10):-11
'~'位操作符(~ -10):9
10的二進制原碼 0000 0000 0000 0000 0000 0000 0000 1010 反碼,補碼 同
~取反操作後:1111 1111 1111 1111 1111 1111 1111 1111 0101 補碼
反碼: 1111 1111 1111 1111 1111 1111 1111 1111 0100
原碼:1000 0000 0000 0000 0000 0000 0000 1011 即 -11
個人猜想:N進行取反操作的結果是不是 -N-1????
^ (異或運算符)
兩個操作數進行異或時,對于同一位上,如果數值相同則為 0,數值不同則為 1。
System.out.println("'^'位操作符(10^3):"+(10^3));
System.out.println("'^'位操作符(9^3):"+(9^3));
System.out.println("'^'位操作符(9^10):"+(9^10));
-------------
輸出結果:
'^'位操作符(10^3):9
'^'位操作符(9^3):10
'^'位操作符(9^10):3
相信從這個例子,你們也應該看明白異或操作的規律了吧。
此外,還可以通過異或實作兩個(長)整型的數值互換(浮點型也是以二進制存儲,為什麼不能進行異或運算?感興趣的可以自己去研究)
int a=48,b=-30;
a=a^b;
b=a^b;
a=b^a;
上面代碼即可實作整型值互換,下面詳細介紹下原理
注:此處為了友善,使用的8bit(位),那些說什麼32位系統 64位系統的杠精可以出門右轉了
a=48 =D(48)= B(0011 0000)
b=-30 =D(-30)= B(1001 1110)
a=a^b
0011 0000
^ 1001 1110
----------------
1010 1110
即 a=a^b=B(0011 0000)^B(1001 1110)=B(1010 1110)=D(-46)=-46
b=a^b
1010 1110
^ 1001 1110
----------------
0011 0000
即 b=a^b=B(1010 1110)^B(1001 1110)=B(0011 0000)=D(48)=48
a=b^a
0011 0000
^ 1010 1110
----------------
1001 1110
即 a=b^a =B(0011 0000)^B(1010 1110)=B(1001 1110)=D(-30)=-30
小結
二進制運算符,包括位運算符和移位運算符,使程式員可以在二進制基礎上操作數字,可以更有效的進行運算,并且可以以二進制的形式存儲和轉換資料,是實作網絡協定解析以及加密等算法的基礎。