1. 程式人生 > >深刻理解Java位移運算子

深刻理解Java位移運算子

 移位操作符操作的運算物件是二進位制的位(Bit),只可用來處理整數型別(基本型別的一種)。移位操作可分為 左移操作符(<<)、“有符號”右移操作符(>>)、“無符號”右移操操作符(>>>)三種。

左移操作符 ( <<): 

value << num     value指定移動的值  num指定移動的位數

運算規則:

  • 按照操作符右側指定的位數將左邊的運算元向左邊移動(高位移除,在低位補0);
  • 當左移的運算元是int型別時,每移動一位它的第31位就要被移除(位數以第0位開始);
  • 當左移的運算元是long型別時,每移動一位 它的第63位就要被移除;
  • 當左邊的運算元為byte、short型別時,它們會被轉換為int型別,其結果要是int型別。
  • 在左移過程中正數可能移為負數,負數也可能移為正數。

數學意義:

  • 在沒有數字溢位的前提下,左移1位相當於乘以2的1次方,左移n位相當於乘以2的n次方。

例:這裡以-101(int型別)為例,負數在計算機內是以補碼形式儲存的,因此移位操作時也是在補碼的基礎上移位。

-101在計算機內的儲存
原始碼 10000000 00000000 00000000 01100101
反碼 11111111 11111111 11111111 10011010
補碼 11111111 11111111 11111111 10011011

由補碼可知,當向左移動到25、26、29位時-101變為正數,以下用程式來說明:

public class NumPlaceMove{
    public static void main(String[] args){
	int a = -101;
	for(int i=1;i<33;i++){
	    System.out.println(a+"<<"+i+"="+(a<<i));
	}
    }
}

 結果:

 

“有符號”右移操作符(>>):

value >> num     value指定移動的值  num指定移動的位數

運算規則:

  • 按照操作符右側指定的位數將操作符左邊的運算元向右移動(採用符號擴充套件機制);
  • 符號擴充套件進行移位,即:若符號為正,則在高位插入0,若符號為負,則在高位插入1(符號位保持不變);
  • 當左邊的運算元為byte、short型別時,它們會被轉換為int型別,其結果要是int型別。

數學意義:

  • 右移一位相當於除以2,右移n位相當於除以2的n次方。

例:-101(int型別32位)

-101右移2位記憶體分析
原始碼 1000,0000 0000,0000 0000,0000 0110,0101 取反----->
反碼 1111,1111 1111,1111 1111,1111 1001,1010 加1 ----->
補碼 1111,1111 1111,1111 1111,1111 1001,1011 >>2----->
移位後補碼 1111,1111 1111,1111 1111,1111 1110,0110 減1----->
反碼 1111,1111 1111,1111 1111,1111 1110,0101 取反----->
原始碼 1000,0000 0000,0000 0000,0000 0001,1010 十進位制為:-26

值得注意的是:無論正負偶數左移一位直接是整除結果,但對於正值奇數結果是除以2後向下取整後的結果。

              對於負值奇數結果是除以2後向上取整結果。如下表:

  正數 負數
偶數(60) 直接除以2(30) 直接除以2(-30)
奇數(61) 除以2後向下取整(30) 除以2後向上取整(-31)

“無符號”右移操作符(>>>)

value >>> num     value指定移動的值  num指定移動的位數

運算規則:

  • 按照操作符右側指定的位數將操作符左邊的運算元向右移動(0擴充套件機制);
  • 移位過程中,無論數值是正數還是負數,都在最高位補0
  • 只對32位和64位值有意義

在Thinking in java 中有這麼一句話:

只有數值右端的低5位才有用,這樣可以防止我們移位超過int型值所具有的位數。(因為2的5次方為32,而int型別只有32位)若對一個long型別的數值進行處理,最後得到的結果也是long型別,此時只會用到數值右端的低6位,以防止移位超過long型數值具有的位數

換言之,如果移動位數超過該型別的最大位數,那麼編譯器會對移動的位數取模。例如果對int型別移位33位,實際上只移動了33%32=1位。具體細節是(int a<<b)如果移位超過數值型別的最大位數,就將b化為二進位制數,取右端的低5位數,再把這5位數化為10進位制,此時這個10進位制就是要將a移動的位數,long 型別同理。

注意:移位運算子不存在“無符號”左移這一說。