天天看點

Java中的位運算符

  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       

小結   

二進制運算符,包括位運算符和移位運算符,使程式員可以在二進制基礎上操作數字,可以更有效的進行運算,并且可以以二進制的形式存儲和轉換資料,是實作網絡協定解析以及加密等算法的基礎。