
go語言寫了一段代碼,為什么一個字節的有符號位與無符號位 計算后的結果不一樣
一、計算機是如何存儲數據的
在計算機中,存儲一個數的時候,都是以補碼的形式存儲的
正數:正數的補碼就等於它的原碼
例如:16 源碼:0001 0000 補碼:0001 0000 //這就是計算機最終存儲的數據
負數:負數的補碼是原碼除符號位以外都取反,然后 + 1 得來的
例如: -16 源碼:1 001 0000 // 計算機在處理負數時最高位代表符號位 所以 最高位的1為 負號 反碼:1 110 1111 //符號位不變 其他數據位取反 補碼:1 110 1111+1=1 111 0000 //反碼+1=補碼 這就是計算機最終存儲的數據
二、有符號與無符號
無符號:其最高位的1或0,和其它位一樣,用來表示該數的大小。
一個字節(1111 1111) 1111 1111=1*2^7+1*2^6+1*2^5+1*2^4+1*2^3+1*2^2+1*2^1+1*2^0=255;所以無符號的一個字節表示的數據范圍是0~255 共 256個;在Go語言中 uint8 范圍(0~255)
例如:100 無符號表示:01100100
有符號:最高數稱為“符號位”。為1時,表示該數為負值,為0時表示為正值。一個字節(0111 1111) 最高位的0表示正號,0111 1111=+111 1111=+(1*2^6+1*2^5+1*2^4+1*2^3+1*2^2+1*2^1+1*2^0)=+127
例如:100 有符號表示:01100100 //最高位0 表示 +號, 后七位才是具體數據位
對於有符號數的運算,一律采用補碼進行;把減法運算轉為加法運行 例如 5-3=5+(-3)
5 補碼:0000 0101 -3 補碼:1111 1101 相加: 10000 0010 // 由於我們是8位bit運算,我們丟棄溢出位1 最后 是 0000 0010=2
計算:5-7=5+(-7)=-2
5 補碼:00000101 -7 補碼:11111001 相加: 11111110 (由於符號位為1 所以改數為補碼) 反碼: 11111101 // 補碼-1 源碼: 10000010 // 反碼除符號位以外取反
對於有符號位的0
源碼:1000 0000
反碼:1111 1111
補碼:1 0000 0000 //去掉溢出位1后 0000 0000
所以對於0 如果采用8bit位 我們規定就用0000 0000 表示,用1000 0000 表示-128
最后我們手動計算該代碼

1 源碼: 0 000 0001
1 補碼: 0 000 0001
127源碼: 0 111 1111
127補碼: 0 111 1111
1補碼+127補碼=1000 0000 由於我們程序采用8bit位有符號類型,所以該結果是-128
三、原碼與補碼的相互轉換
源碼=》補碼 (源碼取反+1)
byte b=-3;
源碼:1000 0011
反碼:1111 1100
補碼:1111 1101
補碼=》源碼 (補碼取反+1)
補碼:1111 1101
反碼:1000 0010
源碼:1000 0011
四、計算機采用補碼的意義
計算機通常用補碼來表示有符號數,計算機的一個數據可以看作是有符號數,也可以看作無符號數的,也就是說計算機並不知道你存的是有符號數還是無符號數,而且所做的運算並不需要管你存的是什么數
使用補碼的原因:簡化計算機基本運算電路,使加減法都只需要用加法電路實現,用加法替代減法。
目的:為了簡化計算機基本運算電路,使加減法都只需要通過加法電路實現,也就是讓減去一個正數或加上一個負數這樣的運算可以用加上一個正數來代替。於是改變負數存儲的形式,存儲成一種可以直接當成正數來相加的形式,這種形式就是補碼。
