此文是基於阮一峯大神的文章-關於2的補碼的學習總結,便於加深印象和回顧,若想看原文,請走剛纔的傳送門~
負數在計算機中如何表示呢?
在計算機內部採用2的補碼(Two’s Complement)表示負數。
什麼是2的補碼?
它是一種數值的轉換方法,要分二步完成:
- 第一步,每一個二進制位都取反值,
0
變成1
,1
變成0
。比如:00001000
取反爲11110111
; 第二步,將上一步的得到的值
+1
。即:11110111 + 1 = 11111000;
所以,11111000
爲00001000
的補碼,也就是說-8
在計算機中用11111000
表示;
爲什麼要用補碼來表示負數呢?
對於計算機,加減乘除是最基本的運算,要儘量設計的很簡單;
- 運算法則減去一個數等於是加上這個數的負數;
- 計算機的基礎電路只有加法,使得設計更加簡單;
由於對於二進制的編碼有三種方式:原碼、反碼和補碼;
- 使用原碼進行
正數 + 負數
的類減法所得的結果並不正確; - 使用反碼進行計算時,結果的真值部分是正確的,但是會有一個特殊的值:
0
。由於0是具有符號位是沒有任何意義的,並且會有1000 0000
和0000 0000
兩個編碼表示0; - 使用補碼進行計算可以完美解決真值、符號位和0的問題,同時由於
(-1) - (-127) = -128
,補碼會以1000 0000
表示 -128,即還能夠表示一個最低數。 - 原碼和反碼錶示的範圍爲
[ -127, 127 ]
,而補碼可以表示[ -128, 127 ]
;
2的補碼的本質:
負數可以換成是 0 - 正數
得到的,因此 對於 -8 可以看做是 0 - (+8)
得到的;
那麼對於二進制的來說即如下形式:
0 0 0 0 0 0 0 0
- 0 0 0 0 1 0 0 0
--------------------------
1 1 1 1 1 0 0 0
因爲 被減數 0000 0000
小於減數 0000 1000
,因此需要向上一位借1,因此實質上被減數是1 0000 0000
;
1 0 0 0 0 0 0 0 0
- 0 0 0 0 1 0 0 0
--------------------------
1 1 1 1 1 0 0 0
進一步觀察可以發現,1 0000 0000
是由 1111 1111 + 0000 0001
所得,因此:
1 1 1 1 1 1 1 1
- 0 0 0 0 1 0 0 0
--------------------------
1 1 1 1 0 1 1 1
+ 0 0 0 0 0 0 0 1
--------------------------
1 1 1 1 1 0 0 0
2的補碼的轉換步驟就是這麼來的;
爲什麼正數加法適用於2的補碼?
事實上,我們要證明的是X - Y
或X + (-Y)
可以用X + Y
的2的補碼完成;
根據上面的所說的,Y的2的補碼可以用1111 1111 - Y + 1
來表示;
即:X + (-Y) => X + ( 1111 1111 - Y + 1 ) = Z
;
基於以上算式,分爲 兩種 情況討論:
- 第一種,X < Y,Z 應該爲負數,那麼對 Z 採用2的補碼的逆運算求出正數值然後在加一個負號即可得到
Z = -[ 1111 1111 - ( Z - 1 ) ]
Z = -[ 1111 1111 - ( X + ( 1111 1111 - Y + 1 ) ) + 1 ] = X - Y;
- 第二種,X > Y,那麼 Z 肯定大於 1111 1111,但是我們假定這是8位機,最高位第9位溢出被捨棄,相當於減去
1 0000 0000
,因此:
Z = Z - 1 0000 0000 = X + ( 1111 1111 - Y + 1 ) - 1 0000 0000 = X - Y
另外,還有一種方法證明:
Z = X - Y = X + 1111 1111 - Y + 1 = X - Y + 1 0000 0000,
由於是8位機,是不可能出現第9位的(被捨去),即
Z = X - Y + 0000 0000 = X - Y;