有符號數處理

計算機進行運算時,需要將負數編碼至二進制形式,所用的編碼方法稱為有符號數的表示

數學中,可以在任意基數的數前面添加負號「−」來表示負數。然而在隨機存取存儲器寄存器中,數據均以一系列二進制位表示而沒有額外的標誌,因此需要一種編碼負號的方法。當前有四種方法,用於擴展二進制數字系統,來表示有符號數:原碼sign-and-magnitude)、反碼ones' complement)、補碼two's complement)以及移碼offset binaryexcess-N)。

原碼

8位原碼
二進制 符號及值 無符號
00000000 +0 0
00000001 1 1
... ... ...
01111111 127 127
10000000 −0 128
10000001 −1 129
... ... ...
11111111 −127 255

符號及值(sign & magnitude)的處理辦法是分配一個符號位(sign bit)來表示這個符號:設置這個(通常為最高有效位)為0表示一個正數,為1表示一個負數。數字中的其它位指示數值(或者絕對值)。因此一個字節只有7位(除去符號位),數值的範圍從0000000(0)到1111111(127)。這樣當你增加一個符號位(第八位)後,可以表示從−12710到+12710的數字。這種表示法導致的結果就是可以有兩種方式表示零,00000000(0)與10000000(−0),這大大增加數碼電路的複雜性和設計難度。CPU亦須執行兩次比較,來測試運算結果是否為零。

十進制數−43用原碼方法編碼成八位的結果為10101011。

這種方法被直接比較於常用的符號表示法(放置一個「+」或者「−」在數字的數值之前)。一些早期的二進制電腦(例如IBM 7090)使用這種表示法,也許是由於它與通用用途的自然聯繫。原碼是最常用的表示浮點數的方法。IEEE二進位浮點數算術標準(IEEE 754)採用最高有效位作為符號位,因此可表示正負及正負無限

反碼

8位反碼
二進制值 反碼表示 無符號數表示
00000000 +0 0
00000001 1 1
... ... ...
01111101 125 125
01111110 126 126
01111111 127 127
10000000 −127 128
10000001 −126 129
10000010 −125 130
... ... ...
11111110 −1 254
11111111 −0 255

另一方面,一種叫做反碼ones' complement)的系統也可以用於表示負數(註:正數與原碼形式一樣,無需取反)。一個負數的二進制數反碼形式為其絕對值部分按位取反(即符號位不變,其餘各位按位取反)。同原碼表示一樣,0的反碼表示形式也有兩種:00000000(+0)與11111111(−0)。

例如,原碼10101011(-43)的反碼形式為11010100(−43)。有符號數用反碼表示的範圍為−(2N−1−1)到(2N−1−1),以及+/−0。一個慣常的八位的字節便是(可表示)−12710到+12710,以及00000000(+0)或者11111111(−0)。

對兩個反碼表示形式的數字做加法,首先需要進行常規的二進制加法,但還需要在和的基礎上加上進位。下面是一個−1加上+2的例子。

       二進制    十進制
    11111110     -1
 +  00000010     +2
............    ...
  1 00000000      0   <-- 錯誤答案
           1     +1   <-- 加上進位
............    ...
    00000001      1   <-- 正確答案

在上面的例子中,二進制加法僅僅得到了00000000,這是一個錯誤的答案。只有當加上進位時才能得到正確答案(00000001)。

反碼這種數字表示系統通常出現在老式的計算機中;PDP-1CDC 160AUNIVAC 1100/2200系列以及其它的一些電腦都使用反碼算術。

關於正字法(orthography)的評述:這個系統之所以被稱作反碼(ones' complement)是因為一個正值x的反(表示為按位非x)也可以通過0的反碼(ones' complement)表示形式(一長串的1,−0)減去x得到。

Internet協議IPv4ICMPUDP以及TCP都使用同樣的16位反碼檢驗和算法。雖然大多數計算機缺少「循環進位」硬件,但是這種額外的複雜性是可以接受的,因為「對於所有位(bit)位置上的錯誤都是同樣敏感的」。[1]UDP中,全0表示省略了可選的檢驗和特性。另外一種表示:FFFF,指示了0的檢驗和。[2] (在IPv4中,TCP和ICMP都強制性地規定了檢驗和,而在IPv6中可以省略)。

注意負數的反碼只需按位求數值的補碼就可以得到,符號不需要變動

補碼

8位補碼
二進制值 補碼表示 無符號數表示
00000000 0 0
00000001 1 1
... ... ...
01111110 126 126
01111111 127 127
10000000 −128 128
10000001 −127 129
10000010 −126 130
... ... ...
11111110 −2 254
11111111 −1 255

補碼two's complement)迴避了0有多種表示的問題以及循環進位的需要。在補碼表示中,負數以位模式表示為正值的反碼加1(當作無符號數)。

在補碼表示中,只有一個0(00000000)。求一個數的補碼(無論是負數還是正數)需要反轉所有位,然後加1。一對補碼整數相加等價於一對無符號數相加(除了溢出檢測,如果能夠做到的話)。比如,從旁邊的表格可以看出,127與−128的補碼表示相加就與無符號數127及128相加具有相同的結果。

從一個正數得到其對應負數的補碼的簡單方法表示如下:

例1 例2
1. 從右邊開始,找到第一個'1' 0101001 0101100
2. 反轉從這個'1'之後開始到最左邊的所有位 1010111 1010100

移碼

移碼(offset binary),是將二進制原碼無符號整數所代表的值,減去一個預設值。

標準移碼,預設值為二進制原碼表示的最大整數的一半。 一個數的標準移碼和補碼,最高位相反,其餘各位均相同。

表示方式

下表列出了 4-bit 二進數所能表示的整數:

  • 無符號(unsigned)可表示0到15
  • 符號及值(sign & magnitude)可表示-7到+7,包括-0
  • 一補碼(ones' complement)可表示-7到+7,包括-0
  • 二補碼(two's complement)可表示-8到+7,沒有±0的問題
二進數 無符號 符號位元 一補碼 二補碼
0000 0 0 0 0
0001 1 1 1 1
0010 2 2 2 2
0011 3 3 3 3
0100 4 4 4 4
0101 5 5 5 5
0110 6 6 6 6
0111 7 7 7 7
1000 8 -0 -7 -8
1001 9 -1 -6 -7
1010 10 -2 -5 -6
1011 11 -3 -4 -5
1100 12 -4 -3 -4
1101 13 -5 -2 -3
1110 14 -6 -1 -2
1111 15 -7 -0 -1

參見

參考資料

  1. ^ Braden, R. Computing the Internet Checksum (RFC 1071). The Internet Engineering Task Force. 1988 [2009-06-11]. (原始內容存檔於2020-10-21). 
  2. ^ Postel, J. User Datagram Protocol (RFC 768). The Internet Engineering Task Force. 1980 [2009-06-11]. (原始內容存檔於2012-07-22).