Java byte位移操做 注意事項

Java byte位移操做 注意事項

Java對byte 的 + - * / >> >>> << & | ^ (加,減,乘,除,右移,左移,無符號右移,位與,位或,位異或)操做,均會是首先將byte轉化爲int, 再行運算。這一事實可能致使多種問題:html

 

假設咱們想進行以下byte運算: 1111 1000 右移1位,再與0000 0001 或運算,得 0111 1101。java

直覺寫程序以下:函數

byte b = 0xf8;spa

byte b2 =  b >> 1 | 0x01;  .net

這個寫法裏有多重錯誤,現逐個糾正:htm

1 編譯器報錯,int沒法直接自動轉化爲byte blog

爲解決此問題,增強制轉化。get

byte b = (byte)0xf8;編譯器

byte b2 = (byte)( (b >> 1) | 0x01);  虛擬機

 

2 輸出爲 1111 1101 不是咱們想要的 0011 1101

緣由是>> 是有符號右移,當符號位爲1時,左側補的是1而非0。

修改成使用 >>> 無符號右移:

byte b = (byte)0xf8;

byte b2 = (byte)( (b >>> 1) | 0x01);  

3 運行後發現輸出依然爲 1111 1101 

緣由是byte在運算前先轉化爲int再行位運算,所以分解後的運算步驟以下:

b 轉化爲int  1111 1000 轉化爲      11111111 11111111 11111111 11111000

無符號右移1位                      01111111 11111111 11111111 11111100

與 0x01 按位或                  01111111 11111111 11111111 11111101

強制轉化回byte     11111101

解決方案,在右移運算前先 位與 0xff

byte b = (byte)0xf8;

byte b2 = (byte)( ((b & 0xff )>>> 1) | 0x01);  //注意必須加括號,由於 >>> 的優先級高於 &

 

4 運行後發現輸出爲咱們想要的結果  0111 1101。運算步驟分解以下:

b 轉化爲int  1111 1000 轉化爲   11111111 11111111 11111111 11111000

和0xff 進行 & 操做              00000000 00000000 00000000 11111000

無符號右移1位   00000000 00000000 00000000 01111100

與 0x01 按位或  00000000 00000000 00000000 01111101

強制轉化回byte  01111101

 

5 關於System.out.println();

byte b = (byte)0xf8;

System.out.println(b);   --最終輸出爲-8

運算步驟爲:

b 轉化爲int  1111 1000 轉化爲   11111111 11111111 11111111 11111000

取符號位 -                      -1111111 11111111 11111111 11111000

取返+1(由於是按補碼運算)      -0000000 00000000 00000000 00001000

輸出  -8

 

最終結論:

1 區分使用 >> 和 >>>

2 在 >> 操做前要首先 & 0xff

3 注意符號優先級,正確使用括號。

4 須要強烈注意的一點是 & 的優先級小於 + . 所以 a = b & 0xff + 2000 的結果 可能不是你想要的

 

附:

打印byte,int 每一個bit值的函數。

 

public static void printByte(byte b){

    for(int i = 7; i >=0 ; i --){

        int shiftleft = (b >> i) & 0x01;

        System.out.print(shiftleft);

    }

    System.out.println();

}

 

public static void printInt(int b){

    for(int i = 31; i >=0 ; i --){

        int shiftleft = (b >> i) & 0x01;

        System.out.print(shiftleft);

    }

    System.out.println();

}

 

http://blog.csdn.net/qq_30739519/article/details/50991484

1.1. java虛擬機整數

在java虛擬機中整數有byte、short、int、long四種 分別表示 8位、16位、32位、64位有符號整數。整數使用補碼錶示。

因此咱們先了解一下原碼和反碼。

1.1.1. 原碼

所謂原碼就是符號位加上數字的二進制表示,int爲例,第一位表示符號 (0正數 1負數)簡單期間一個字節表示

+7的原碼爲: 00000111
 -7的原碼爲: 10000111

對於原碼來講,絕對值相等的正數和負數只有符號位不一樣。

1.1.2. 反碼

一個數若是爲正,則它的反碼與原碼相同;一個數若是爲負,則符號位爲1,(符號位不變化,其他位數取反)。

換言之 該數的絕對值取反(絕對值取反各位都取反)。
爲了簡單起見,咱們用1個字節來表示一個整數:
     +7的反碼爲:00000111
     -7的反碼爲: 11111000

1.1.3. 補碼

補碼:一個數若是爲正,則它的原碼、反碼、補碼相同;一個數若是爲負,去到反碼而後加1。(反碼加1就是補碼)爲了簡單起見,咱們用1個字節來表示一個整數:
+7的補碼爲: 00000111
-7的補碼爲: 11111001

1.1.4. 總結

正數:它的原碼、反碼、補碼相同。

負數:反碼符號位不變化,其他位數取反,補碼符號位不變化其他各位原碼取反(反碼)+1換言之 反碼+1

 

已知一個負數原碼求反碼:

步驟:

1.該數的絕對值取反 

已知一個負數反碼去求補碼:

1.反碼+1

 

已知一個負數求反碼步驟:

正數的絕對值取反+1

 

已知一個負數求補碼步驟:

1.二進制原碼錶示 

2.符號位不變化爲1 求反碼。

3.符號位不變化,其他的加1.

實例以下:

-10求補碼步驟:

-10的原碼: 10000000 00000000 00000000 00001010

-10的反碼: 11111111 11111111 11111111  11110101

-10的補碼:11111111 11111111 11111111 11110110

 

已知一個負數的補碼,將其轉換爲十進制數,步驟

   一、先對各位取反;
      二、將其轉換爲十進制數;
      三、加上負號,再減去1。

  例如:

11111010,最高位爲1,因此是負數,先對各位取反得00000101,轉換爲十進制數得5,加上負號得-5,再減1得-6。

1.1.5. Java byte 類型的取值範圍

1.肯定byte是1個字節,也就是8位。

2.最大值 0111 1111

3.最小值 1000 0000。

4.0111 1111 就是127。

5.1000 0000 減去1是 1111 1111 按照位取反 1000 0000 獲得-128

1.1.6. 常見問題

int a=232;

 

//0000 0000 1110 1000

System.out.println(Integer.toBinaryString(a));

System.out.println((byte) a);

輸出結果爲-24:

原理以下圖:

相關文章
相關標籤/搜索