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
在java虛擬機中整數有byte、short、int、long四種 分別表示 8位、16位、32位、64位有符號整數。整數使用補碼錶示。
因此咱們先了解一下原碼和反碼。
所謂原碼就是符號位加上數字的二進制表示,int爲例,第一位表示符號 (0正數 1負數)簡單期間一個字節表示
+7的原碼爲: 00000111
-7的原碼爲: 10000111
對於原碼來講,絕對值相等的正數和負數只有符號位不一樣。
一個數若是爲正,則它的反碼與原碼相同;一個數若是爲負,則符號位爲1,(符號位不變化,其他位數取反)。
換言之 該數的絕對值取反(絕對值取反各位都取反)。
爲了簡單起見,咱們用1個字節來表示一個整數:
+7的反碼爲:00000111
-7的反碼爲: 11111000
補碼:一個數若是爲正,則它的原碼、反碼、補碼相同;一個數若是爲負,去到反碼而後加1。(反碼加1就是補碼)爲了簡單起見,咱們用1個字節來表示一個整數:
+7的補碼爲: 00000111
-7的補碼爲: 11111001
正數:它的原碼、反碼、補碼相同。
負數:反碼符號位不變化,其他位數取反,補碼符號位不變化其他各位原碼取反(反碼)+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.肯定byte是1個字節,也就是8位。
2.最大值 0111 1111
3.最小值 1000 0000。
4.0111 1111 就是127。
5.1000 0000 減去1是 1111 1111 按照位取反 1000 0000 獲得-128
int a=232;
//0000 0000 1110 1000
System.out.println(Integer.toBinaryString(a));
System.out.println((byte) a);
輸出結果爲-24:
原理以下圖: