移位運算符操做的對象就是二進制的位,能夠單獨用移位運算符來處理int型整數。html
運算符 | 含義 | 例子 |
<< | 左移運算符,將運算符左邊的對象向左移動運算符右邊指定的位數(在低位補0) | x<<3 |
>> | "有符號"右移運算 符,將運算符左邊的對象向右移動運算符右邊指定的位數。使用符號擴展機制,也就是說,若是值爲正,則在高位補0,若是值爲負,則在高位補1. | x>>3 |
>>> | "無符號"右移運算 符,將運算符左邊的對象向右移動運算符右邊指定的位數。採用0擴展機制,也就是說,不管值的正負,都在高位補0. | x>>>3 |
以int類型的6297爲例,代碼以下:java
運行結果:面試
1100010011001
11111111111111111110011101100111
11000100
11111111111111111111111100111011
11000100
111111111111111111100111011
110001001100100000
11111111111111001110110011100000編程
注:x<<y 至關於 x*2y ;x>>y至關於x/2y
從計算速度上講,移位運算要比算術運算快。
若是x是負數,那麼x>>>3沒有什麼算術意義,只有邏輯意義。segmentfault
在Think in Java中有這麼一段話post
「對char,byte或者short進行移位處理,那麼在移位進行以前,它們會自動轉換成一個int。只有右側的5個低位纔會有用。這樣可防止咱們在一個int數裏移動不切實際的位數。若對一個long值進行處理,最後獲得的結果也是long。此時只會用到右側的6個低位,防止移動超過long值裏現成的位數。」測試
這段話有兩個出處,一個是Java編程思想3.11移位操做符中出現,原話是「只有數值右端的低5位纔有用」。一個是Java解惑中謎題27:變幻莫測的i值,原話是「移位操做符只使用其右操做數的低5位做爲移位長度」。spa
弄清這句話首先須要弄清楚移位操做符,移位操做符是一個二元操做符,兩個操做數分別位於移位操做兩邊形如:左操做數 移位操做符 右操做數 這樣的結構,其含義是,將左操做數按照移位操做符指定的移位方向,進行右操做數指定的次數的移位。而後對照出處二,Java解惑中所描述的,就豁然開朗了。.net
首先,移位操做符能操做的數只有int類型和long類型,這個是指左操做數的類型。對於int類型而言,int在Java中佔4字節,一共32位,也就是說,對於一個在Java中的int數據,作32次移位,那麼這個int數據就徹底變了,以左移爲例,左移是補0,那麼對於任意一個int類型數據,作32次移位,那麼int數據變成32位全0的數據,Java不容許一次性移位左操做數的全部位,也就是右操做數不能大於32。因而回到上述的句子,其指的是右操做數的低5位,5位二進制所表明的最大值爲2^5-1,爲31,因此取右操做數的低5位,就是隻看右操做數的二進制的低5位,其數值不會超過2^5次方,也就是int的32位。所以,移位操做符進行移位的實際次數,實際上是右操做數2的次數。code
對上面那段話的理解是:移位操做符操做的運算對象是二進制的「位」,int類型是32位也就是2的5次冪 !若是移32位以上,那麼原來的數的信息會所有丟失,這樣也就沒有什麼意義了!因此上面的「只有右側的5個低位纔會有用」說的是:移位操做符右端的那個數(化成二進制)的低5位纔有用,即
X < <y;
是指y的低5位纔有用,即不能大於32。 而對於long型也是一樣的道理!
所以,若是對一個int 型,進行移位,X < <y; 當y小於32時,移位後的結果通常都在咱們的預料當中;而若是y大於32時,因爲移位超出了int所能表示的範圍,這時就先把y化成二進制數,而後取該二進制數右端的低5位,再把這5位化成十進制,此時的這個十進制就是要對X移動的位數。
例如:
int int a=140; a << 34 System.out.println(Integer.toBinaryString(a << b));
上面那兩個語句的執行過程是:先把a化成二進制數:10001100
執行語句 a << 34 對a左移32位時,先把 34化成二進制:100010,對該二進制數取右邊5位,即00010,化成十進制數爲2,因此其實是對a左移兩位。如今,地球人都會知道上面程序的輸出結果是:1000110000
//////////////////////////////////////////////////
移位運算符和按位運算符同樣,同屬於位運算符,所以移位運算符的位指的也是二進制位。它包括如下幾種:
左移位(<<):將操做符左側的操做數向左移動操做符右側指定的位數 。移動的規則是在二進制的低位補0。
有符號右移位(>>):將操做符左側的操做數向右移動操做符右側指定的位數。移動的規則是,若是被操做數的符號爲正,則在二進制的高位補0;若是被操做數的符號爲負,則在二進制的高位補1。
無符號右移位(>>>):將操做符左側的操做數向右移動操做符右側指定的位數。移動的規則是,不管被操做數的符號是正是負,都在二進制位的高位補0。
注意,移位運算符不存在「無符號左移位(<<<)」一說。與按位運算符同樣,移位運算符能夠用於byte、short、int、long等整數類型,和字符串類型char,可是不能用於浮點數類型float、double;固然,在Java5.0及以上版本中,移位運算符還可用於byte、short、int、long、char對應的包裝器類。咱們能夠參照按位運算符的示例寫一個測試程序來驗證,這裏就再也不舉例了。
與按位運算符不一樣的是,移位運算符不存在短路不短路的問題。
寫到這裏就不得不說起一個在面試題中常常被考到的題目:
請用最有效率的方法計算出2乘以8等於幾?這裏所謂的最有效率,實際上就是經過最少、最簡單的運算得出想要的結果,而移位是計算機中至關基礎的運算了,用它來實現準沒錯了。左移位「<<」把被操做數每向左移動一位,效果等同於將被操做數乘以2,而2*8=(2*2*2*2),就是把2向左移位3次。所以最有效率的計算2乘以8的方法就是「2<<3」。
最後,咱們再來考慮一種狀況,當要移位的位數大於被操做數對應數據類型所能表示的最大位數時,結果會是怎樣呢?好比,1<<35=?呢?
這裏就涉及到移位運算的另一些規則:
byte、short、char在作移位運算以前,會被自動轉換爲int類型,而後再進行運算。 byte、short、int、char類型的數據通過移位運算後結果都爲int型。 long通過移位運算後結果爲long型。
在左移位(<<)運算時,若是要移位的位數大於被操做數對應數據類型所能表示的最大位數,那麼先將要求移位數對該類型所能表示的最大位數求餘後,再將被操做數移位所得餘數對應的數值,效果不變。
好比1<<35=1<<(352)=1<<3=8。 對於有符號右移位(>>)運算和無符號右移位(>>>)運算,當要移位的位數大於被操做數對應數據類型所能表示的最大位數時,那麼先將要求移位數對該類型所能表示的最大位數求餘後,再將被操做數移位所得餘數對應的數值,效果不變。。
好比100>>35=100>>(352)=100>>3=12。
另:
public static String toBinaryString(int i) //以二進制(基數 2)無符號整數形式返回一個整數參數的字符串表示形式。 //若是參數爲負,該無符號整數值爲參數加上 2^32;不然等於該參數。
System.out.println(Integer.toBinaryString(-1)) ; System.out.println(Integer.toBinaryString(2)) ; System.out.println(Integer.toBinaryString(1)) ;
輸出: 11111111111111111111111111111111 11111111111111111111111111111110 1
結論輸出的是數字的二進制補碼。爲何說是以 二進制無符號整數形式 返回一個 整數類型的字符串,爲何 若是參數爲負數,就要加上 232 次方?
由於Java裏的int是有符號的,在內存中沒有正負之分,只有0/1,整數是用補碼錶示的
正數補碼等於原碼
負數的補碼等於其絕對值的反碼+1,正好等於自身+2^32(對於4字節的整型來講)
-1
的補碼 就是 絕對值1
的反碼(按位取反) 11111111 11111111 11111111 11111110
再+1
等於 11111111 11111111 11111111 11111111
這樣正好能把最高位爲1的數字用來表示負數,而最高位爲0的數字表示非負數
10000000 00000000 00000000 00000000 => -2147483648 11111111 11111111 11111111 11111111 => -1 00000000 00000000 00000000 00000000 => 0 00000000 00000000 00000000 00000001 => 1 01111111 11111111 11111111 11111111 => 2147483647
所以負數+2^32
以後的二進制串,就是該負數內存中準確的存儲形式
參考、轉載:
http://blog.sina.cn/dpool/blog/s/blog_6f436a590100nc37.html?vt=4
https://segmentfault.com/q/1010000002535852
http://blog.sina.com.cn/s/blog_6ca0f5eb0102vlha.html
http://www.cnblogs.com/bluestorm/p/5795461.html