深刻理解Java位移運算子
移位操作符操作的運算物件是二進位制的位(Bit),只可用來處理整數型別(基本型別的一種)。移位操作可分為 左移操作符(<<)、“有符號”右移操作符(>>)、“無符號”右移操操作符(>>>)三種。
左移操作符 ( <<):
value << num value指定移動的值 num指定移動的位數
運算規則:
- 按照操作符右側指定的位數將左邊的運算元向左邊移動(高位移除,在低位補0);
- 當左移的運算元是int型別時,每移動一位它的第31位就要被移除(位數以第0位開始);
- 當左移的運算元是long型別時,每移動一位 它的第63位就要被移除;
- 當左邊的運算元為byte、short型別時,它們會被轉換為int型別,其結果要是int型別。
- 在左移過程中正數可能移為負數,負數也可能移為正數。
數學意義:
- 在沒有數字溢位的前提下,左移1位相當於乘以2的1次方,左移n位相當於乘以2的n次方。
例:這裡以-101(int型別)為例,負數在計算機內是以補碼形式儲存的,因此移位操作時也是在補碼的基礎上移位。
原始碼 | 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位)
原始碼 | 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 型別同理。
注意:移位運算子不存在“無符號”左移這一說。