java位移運算符3 轉

https://www.cnblogs.com/winsker/p/6728672.htmlhtml

移位運算符操做的對象就是二進制的位,能夠單獨用移位運算符來處理int型整數。java

理解java移位運算符
運算符 含義 例子
<< 左移運算符,將運算符左邊的對象向左移動運算符右邊指定的位數(在低位補0) x<<3
>> "有符號"右移運算 符,將運算符左邊的對象向右移動運算符右邊指定的位數。使用符號擴展機制,也就是說,若是值爲正,則在高位補0,若是值爲負,則在高位補1. x>>3
>>> "無符號"右移運算 符,將運算符左邊的對象向右移動運算符右邊指定的位數。採用0擴展機制,也就是說,不管值的正負,都在高位補0. x>>>3

 

 

 

 

 

 

 

 

 

 

 

以int類型的6297爲例,代碼以下:面試

1 System.out.println(Integer.toBinaryString(6297));   
2 System.out.println(Integer.toBinaryString(-6297));   
3 System.out.println(Integer.toBinaryString(6297>>5));   
4 System.out.println(Integer.toBinaryString(-6297>>5));   
5 System.out.println(Integer.toBinaryString(6297>>>5));   
6 System.out.println(Integer.toBinaryString(-6297>>>5));   
7 System.out.println(Integer.toBinaryString(6297<<5));   
8 System.out.println(Integer.toBinaryString(-6297<<5));  

 

運行結果:segmentfault

1100010011001post

11111111111111111110011101100111
11000100
11111111111111111111111100111011
11000100
111111111111111111100111011
110001001100100000
11111111111111001110110011100000測試

 

注:x<<y 至關於 x*2;x>>y至關於x/2y
    從計算速度上講,移位運算要比算術運算快。
    若是x是負數,那麼x>>>3沒有什麼算術意義,只有邏輯意義。spa

結果分析:code

位數:htm

00000000 00000000 00000000 00000000對象

6297
00000000 00000000 00011000 10011001
-6297
10000000 00000000 00011000 10011001   源碼
11111111  11111111   11100111   01100110  反碼 除符號位按位取反

11111111  11111111   11100111   01100111   補碼 除符號位反碼加1

6297>>5

00000000 00000000 00000000 11000100 <右移5位後>

-6297>>5

11111111 11111111 11100111 01100111 補碼<十進制負數在計算機中二進制表示形式>

11111111 11111111 11111111  00111011 <右移5位後>

6297>>>5

00000000 00000000 00011000 10011001

00000000 00000000 00000000 11000100 <右移5位後>

-6297>>>5

11111111 11111111 11100111 01100111 補碼<十進制負數在計算機中二進制表示形式>

0000011 11111111 111111111 00111011 <邏輯右移5位後> 存疑

6297<<5

00000000 00000000 00011000 10011001

00000000 00000011 00010011 00100000

-6297<<5

11111111  11111111   11100111   01100111   補碼 除符號位反碼加1<計算機中負數的存在形式>

11111111  11111100  11101100   11100000  <左移五位後>

=======================================================================

首先,移位操做符能操做的數只有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的次數。

5位二進制所表明的最大值爲2^5-1(注:2^5-1 -->32-1 = 31),爲31
位數
0  0  0  0  0
每位的值
16 8  4  2  1
推測1:01111 -->15
推測2: 11111 -->31<無符號位>

對上面那段話的理解是:移位操做符操做的運算對象是二進制的「位」,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<<(35%32)=1<<3=8。 對於有符號右移位(>>)運算和無符號右移位(>>>)運算,當要移位的位數大於被操做數對應數據類型所能表示的最大位數時,那麼先將要求移位數對該類型所能表示的最大位數求餘後,再將被操做數移位所得餘數對應的數值,效果不變。。

好比100>>35=100>>(35%32)=100>>3=12。

另:

Java 的 Integer.toBinaryString 方法

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以後的二進制串,就是該負數內存中準確的存儲形式

相關文章
相關標籤/搜索