有符號數處理

在電腦進行運算時，需要將負數編碼至二進位形式，所用的編碼方法稱為有符號數的表示。

在數學中，可以在任意基數的數前面添加負號「−」來表示負數。然而在隨機存取存儲器和寄存器中，數據均以一系列二進位位表示而沒有額外的標誌，因此需要一種編碼負號的方法。當前有四種方法，用於擴展二進位數字系統，來表示有符號數：原碼（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）位置上的錯誤都是同樣敏感的」。在UDP中，全0表示省略了可選的檢驗和特性。另外一種表示：FFFF，指示了0的檢驗和。（在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'｜0101001｜0101100

- 反轉從這個'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