問題
最近學(xué)習(xí)java 位操作,取反運(yùn)算遇到了問題。
public class bitMpt {
public static void main(String[] args) {
int a = 128;
int b = 129;
int c = 2;
System.out.println("a and b result: "+(a&b));
System.out.println("a or b result: "+(a|b));
System.out.println("~ c result: "+(~c));
System.out.println("a ^ b result: "+(a^b));
}
}
c = 2 取反,10變01, 結(jié)果應(yīng)該為1,但運(yùn)行結(jié)果為-3。
知識(shí)點(diǎn)
java存儲(chǔ)的是有符號(hào)數(shù),在計(jì)算機(jī)中,有符號(hào)數(shù)通常是使用補(bǔ)碼存儲(chǔ)的。
原碼
原碼就是符號(hào)位加上真值的絕對(duì)值,即用第一位表示符號(hào), 其余位表示值. 比如如果是8位二進(jìn)制:
[+1]原 = 0000 0001
[-1]原 = 1000 0001
第一位是符號(hào)位. 正數(shù)符號(hào)位為0,負(fù)數(shù)為1。
反碼
正數(shù)的反碼是其本身
負(fù)數(shù)的反碼是在其原碼的基礎(chǔ)上,符號(hào)位不變,其余各個(gè)位取反.
例如:
[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反
補(bǔ)碼
正數(shù)的補(bǔ)碼就是其本身
負(fù)數(shù)的補(bǔ)碼是在反碼的基礎(chǔ)上+1。
例如:
[+1] = [00000001]原 = [00000001]反 = [00000001]補(bǔ)
[-1] = [10000001]原 = [11111110]反 = [11111111]補(bǔ)
總結(jié)
所以回到一開始的問題,int a = 2 a在計(jì)算機(jī)中是以補(bǔ)碼存儲(chǔ)的。
對(duì)于2這個(gè)正數(shù)來說,補(bǔ)碼、反碼、原碼都是相同的,又由于是數(shù)值型,在這里我先用八位bit來表示一下:
原碼:0000 0010反碼:0000 0010
補(bǔ)碼:0000 0010
取反取反過程是在補(bǔ)碼的基礎(chǔ)上進(jìn)行的,由于是按位取反,無論符號(hào)位還是數(shù)值位都要取反,所以結(jié)果如下:
取反后的補(bǔ)碼: 1111 1101
換算為值那么取反后的補(bǔ)碼的實(shí)際值是多少呢?我們需要先把他轉(zhuǎn)化為原碼,過程如下:
反碼 = 1111 1101 - 1 = 1111 1100
原碼 = 反碼符號(hào)位不變,其余取反 = 1000 0011
所以,最后的值-3
<small>[參考] https://segmentfault.com/a/1190000004877495