有符號數處理
在計算機進行運算時,需要將負數編碼至二進制形式,所用的編碼方法稱為有符號數的表示。
在數學中,可以在任意基數的數前面添加負號「−」來表示負數。然而在隨機存取存儲器和寄存器中,數據均以一系列二進制位表示而沒有額外的標誌,因此需要一種編碼負號的方法。當前有四種方法,用於擴展二進制數字系統,來表示有符號數:原碼(sign-and-magnitude)、反碼(ones' complement)、補碼(two's complement)以及移碼(offset binary,excess-N)。
原碼
二進制 | 符號及值 | 無符號 |
---|---|---|
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)採用最高有效位作為符號位,因此可表示正負零及正負無限。
反碼
二進制值 | 反碼表示 | 無符號數表示 |
---|---|---|
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-1,CDC 160A,UNIVAC 1100/2200系列以及其它的一些電腦都使用反碼算術。
關於正字法(orthography)的評述:這個系統之所以被稱作反碼(ones' complement)是因為一個正值x的反(表示為按位非x)也可以通過0的反碼(ones' complement)表示形式(一長串的1,−0)減去x得到。
Internet協議IPv4,ICMP,UDP以及TCP都使用同樣的16位反碼檢驗和算法。雖然大多數計算機缺少「循環進位」硬件,但是這種額外的複雜性是可以接受的,因為「對於所有位(bit)位置上的錯誤都是同樣敏感的」。[1] 在UDP中,全0表示省略了可選的檢驗和特性。另外一種表示:FFFF,指示了0的檢驗和。[2] (在IPv4中,TCP和ICMP都強制性地規定了檢驗和,而在IPv6中可以省略)。
注意負數的反碼只需按位求數值的補碼就可以得到,符號不需要變動。
補碼
二進制值 | 補碼表示 | 無符號數表示 |
---|---|---|
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 |
參見
參考資料
- ^ Braden, R. Computing the Internet Checksum (RFC 1071). The Internet Engineering Task Force. 1988 [2009-06-11]. (原始內容存檔於2020-10-21).
- ^ Postel, J. User Datagram Protocol (RFC 768). The Internet Engineering Task Force. 1980 [2009-06-11]. (原始內容存檔於2012-07-22).