一、計算機的負數表示
二、1的補碼one's complement——反碼
三、2的補碼two's complement——補碼
資料在計算機中由乙個乙個的0,1位元表示,所以在表示負數的時候,不能直接新增符號'-'來表示這是個負數,必須採用一些規範或者約定來區分正數和負數。
有四種比較有名的表示負數的方法:原碼(sign-and-magnitude),1的補碼(one's complement),2的補碼(two's complement),以及excess-k(即offset binary)。
1、特性
1的補碼比較簡單,它在表示負數的時候簡單把該負數的絕對值(即相應的正數)的二進位制位全部反轉。比如1用0000 0001表示,那麼-1就用1111 1110表示。
比較有意思的是由於+0用0000 0000表示,反轉後1111 1111就表示-0。所以在1的補碼裡有兩個零。
binary value
ones' complement interpretation
unsigned interpretation
00000000+00
0000000111
⋮⋮⋮01111101
125125
01111110
126126
01111111
127127
10000000
−127
12810000001
−126
12910000010
−125
130⋮⋮⋮
11111101
−2253
11111110
−1254
11111111
−0255
from
以上表舉例來看:(-1)+1 = 0,對應的1的補碼加法
0000 0001 ——-1
+1111 1110 ——1
*****====
1111 1111——-0
由於負數都是由相應的正數二進位制位全反轉得到的,所以這裡有個特性就是把它們相加的話會得到乙個二進位制位為全1的數,在1的補碼的表示方法中,全1表示-0。這也是為什麼這種表示方法叫做"1的補碼"。1的補碼在ip,tcp,udp,icmp等協議頭中應用於計算校驗和。
還有一點很有意思的是,在1的補碼表示的數中,所有的正數最高位元都是0,而所有的負數最高位元都是1。而且它的正最大值是127,沒有向上加過去表示128。在我們平常來看,最高位表示符號位0代表正,1代表負是極為正常的事。但是在1的補碼裡,沒有設定符號位,之所以造成這樣的"巧合",存在著一定的必然性。我們假設它能表示到128,即1000 0000,那麼-128就表示成0111 1111,可是0111 1111已經用來表示127了,這就造成了衝突。其實問題很簡單,我們可以把最高位的0,1看作是字首碼,用這位字首碼保證對正數的反轉操作不存在衝突。這也是為什麼正數最大只能表示到127。
更有意思的是,國內將1的補碼翻譯成反碼,其求負數的反碼時,"保留符號位,將其餘的位元進行反轉"。但是這樣就不能解釋為什麼有-0的存在。更不能解釋在ip,tcp,udp,icmp協議頭里求校驗和時所謂的"反碼求和"是怎麼回事。
想象有一根數軸,兩端分別向正無窮和負無窮延伸,從中間0的位置一刀劈下去(0有兩個),分成非負和非正的兩半。
這根軸看起來很對稱。
如果我們從+0開始數數,即從0000 0000開始不斷加1(0000 0001,0000 0002,0000 0003…),我們會發現我們不停在迴圈('0'-'127','-127'-'0')。原因是當我們數到127(0111 1111)時,再加1變成-127(1000 0000)。這個時候看起來是這樣的:
2、1的補碼的加法
1的補碼的加法跟其它的加法是一樣的,只是它有個迴圈進製(end-around carry)概念。它要求把最後結果的進製加回到最後的結果中去。
比如計算(-1)+2:
1111 1110
+0000 0010
*****====
(1)0000 0000
+ 1 進製
*****====
0000 0001
為什麼要這樣呢?
我們考慮在①+127處,我們加1變成-127,在-127處我們再減1,同樣會出錯。在應用的時候我們要注意這種超出範圍的錯誤。②處,由於我們有兩個零,在做加法時,我們要加回乙個0去。比如還是計算(-1)+2,
我們拿上面的圈來想象計算的過程,繞著圈順時針走步,圈上的每乙個數字對應乙個走步,計算(-1)+2,也即在(-1)處走兩步,我們走到+0處。由於正常的運算中沒有兩個0,我們在最後回加乙個1。
由於溢位,得到的結果等於0(0000 0000),就是因為中間-0占用了乙個計數,我們把進製1加最後結果上,得到正確結果1:
1111 1110
+0000 0010
*****====
(1)0000 0000
+ 1
*****====
0000 0001
減法可以用加法來表示。
1、從1的補碼的角度來理解補碼加法
負數的補碼經常用反碼加一來計算。將補碼與1的補碼加法聯絡起來可以理解為什麼可以用補碼加法代替減法。
將1的補碼中-0的編碼空出來給-1用,後續數值依次前移,最後1000 0000會空出來,我們給它分配-128。因此,我們可以取值[-1,-128]u[0,127]。
因此,補碼根據反碼(即前文1的補碼)加一來計算其實就是把-0擠掉,留了個位置給-128。
binary value
two's complement interpretation
unsigned interpretation
0000000000
0000000111
⋮⋮⋮01111110
126126
01111111
127127
10000000
−128
12810000001
−127
12910000010
−126
130⋮⋮⋮
11111110
−2254
11111111
−1255
from
那為什麼可以用補碼來計算減法呢?理解了反碼的加法,其實就不難理解為什麼補碼可以直接用來計算減法了。
2、快速寫出補碼
正數的補碼是它本身。
負數的補碼:
從右往左看,從第乙個1出現的位置的下一位開始,反轉位元,符號位不反轉。比如(11010110) 的補碼為10101010。
128的補碼及原碼 反碼 補碼
乙個位元組佔8位 乙個字長為n的機器數能表示不同的數字的個數是固定的2 n個,n 8時2 n 256 用來表示有符號數,數的範圍就是 2 n 1 2 n 1 1,n 8時,這個範圍就是 128 127。用來表示無符號數,就不需要用一位來表示符號位,n位機器數全部用來表示是數值,這時表示數的範圍就是0...
關於2的補碼
日期 2009年8月 5日 問乙個基本的問題。負數在計算機中如何表示?舉例來說,8在計算機中表示為二進位制的1000,那麼 8怎麼表示呢?很容易想到,可以將乙個二進位制位 bit 專門規定為符號位,它等於0時就表示正數,等於1時就表示負數。比如,在8位機中,規定每個位元組的最高位為符號位。那麼,8就...
關於2的補碼
問乙個基本的問題。負數在計算機中如何表示?舉例來說,8在計算機中表示為二進位制的1000,那麼 8怎麼表示呢?很容易想到,可以將乙個二進位制位 bit 專門規定為符號位,它等於0時就表示正數,等於1時就表示負數。比如,在8位機中,規定每個位元組的最高位為符號位。那麼,8就是00001000,而 8則...