二進制負數以它正值的補碼形式表達
補碼:反碼+1等於補碼
比如:System.out.println(Integer.toBinaryString(-5));
打印:1111 1111 1111 1111 1111 1111 1111 1011 不用想了肯定是32位
過程是這樣的
一個負數,比如-5,它的二進制在java裏面是這樣表示
1000 0000 0000 0000 0000 0000 0000 0101
它的正值是
0000 0000 0000 0000 0000 0000 0000 0101
反碼是
1111 1111 1111 1111 1111 1111 1111 1010
再加上1是
1111 1111 1111 1111 1111 1111 1111 1011
即得到打印的內容
java ~ 操作符,對每個二進制位的內容求反,即1變成0,0變成1
測試負數
int a = -5;//101;
System.out.println(~a);
打印:4
過程是這樣的,首先表示出來這個負數
1111 1111 1111 1111 1111 1111 1111 1011(上面已經提到爲什麼這樣表示)
各位取反得到
0000 0000 0000 0000 0000 0000 0000 0100
轉爲10進製得到4
測試正數:
int a = 5;//101;
System.out.println(~a);
打印:-6
首先表示出來這個正數
0000 0000 0000 0000 0000 0000 0000 0101
各位取反得到
1111 1111 1111 1111 1111 1111 1111 1010
這個代表的就是-6了,至於爲什麼看最上面
java & 操作符,對應的二進制位進行與操作,兩個都爲1才爲1,其他情況均爲0
測試
System.out.println(5&6);
打印:4
過程
5表示成:0000 0000 0000 0000 0000 0000 0000 0101
6表示成:0000 0000 0000 0000 0000 0000 0000 0110
進行 & :0000 0000 0000 0000 0000 0000 0000 0100
得到:4
java | 操作符,對應的二進制位進行或操作,兩個都爲0才爲0,其他情況均爲1
測試
System.out.println(5|6);
打印:7
過程
5表示成:0000 0000 0000 0000 0000 0000 0000 0101
6表示成:0000 0000 0000 0000 0000 0000 0000 0110
進行 | :0000 0000 0000 0000 0000 0000 0000 0111
得到:7
java ^ 操作符 當對應二進制位值相同,該位爲0 否則爲1
測試
System.out.println(5^6);
打印:3
過程
5表示成:0000 0000 0000 0000 0000 0000 0000 0101
6表示成:0000 0000 0000 0000 0000 0000 0000 0110
進行 ^ :0000 0000 0000 0000 0000 0000 0000 0011
得到:3
java << 操作符,左邊移動,右面填充0
測試
System.out.println(5<<1);
打印:10
5表示成:0000 0000 0000 0000 0000 0000 0000 0101
進行 <<1 操作:0000 0000 0000 0000 0000 0000 0000 1010
java >> 操作符,左邊移動,右面填充0
測試
System.out.println(5>>>1);
打印:2
5表示成:0000 0000 0000 0000 0000 0000 0000 0101
進行 >>>1 操作:0000 0000 0000 0000 0000 0000 0000 0010
左移動一位相當乘以2 右移動一位相當處以2
package c03;
public class URShift {
public static void main(String[] args) {
int i = -1;
i >>>= 10;
System.out.println(i);
}
}
其結果爲:4194303
怎麼來的呢?
因爲java裏的int型是32位的,且負數的存儲以補碼(符號位保持不變,其他位是存儲數的絕對值按位取反加1)方式:故而-1在存儲空間的存放爲:
其值爲2^32-1=4294967255;
故而無符號右移10位:變成如下圖所示:
其值爲2^22-1=4194303;
對於帶符號右移,若爲負數,則在存儲時首位表示符號位,其值爲1,表示該值是負數的移位,在移位過程中,高位補1,若符號位是0,表示是正數,在移位過程中高位補零,兩者的前提是符號位保持不變:
package c03;
public class URShift {
public static void main(String[] args) {
int i = -1, j = 10000;
i >>= 10;
j >>= 10;
System.out.println(i + ", " + j);
}
}
輸出爲:-1, 9
拿-1爲例,因爲右移,高位補1,所以-1的右移始終不變.
然後求補碼加1;
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
再例,-100帶符號右移四位,其值爲-7:
原碼爲:
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
補碼爲:
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
右移四位後:
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
保留符號位,按位取反:
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
再加1,即得原碼:
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |