在[[计算机运算]]中,'''有符号数的表示'''需要将负数编码为二进制形式。
在[[数学]]中,任意基数的负数都在最前面加上“−”“−”符号来表示。然而在计算机[[硬件]]中,数字都以无符号的二进制形式表示,因此需要一种[[编码]][[负号]]的方法。当前有四种方法,用于扩展[[二进制数字系统]],来表示[[有符号数]]:原码(sign-and-magnitude),[[反码]](ones' complement),[[补码]](two's complement),以及[[移码]]excess-''N''。
==原码==
|}'''
符號及值(sign & magnitude)的处理办法是分配一个符号位(sign bit)来表示这个符号:设置这个[[位]](通常为[[最高有效位]])为''0''表示一个正数,为''1''表示一个负数。数字中的其它位指示数值(或者[[绝对值]])。因此一个[[字节]]只有7位(除去符号位),数值的范围从0000000(0)到1111111(127)。这样当你增加一个符号位(第八位)后,可以表示从−127−127<sub>10</sub>到+127<sub>10</sub>的数字。这种表示法导致的结果就是可以有两种方式表示零,00000000(0)与10000000([[-0|−0−0]]),這大大增加[[數碼電路]]的複雜性和設計難度。CPU亦須執行兩次比較,來測試運算結果是否為零。
十进制数−43−43用原码方法编码成八位的结果为10101011。
这种方法被直接比较于常用的符号表示法(放置一个“+”或者“−”“−”在数字的数值之前)。一些早期的二进制电脑(例如[[IBM 7090]])使用这种表示法,也许是由于它与通用用途的自然联系。原码是最常用的表示[[浮點數]]的方法。[[IEEE 754|IEEE二進位浮點數算術標準]](IEEE 754)採用最高有效位作為符号位,因此可表示正負[[零]]及正負[[無限]]。
==反码==
|}
另一方面,一种叫做'''反码'''的系统也可以用于表示负数(注:正数与原码形式一样,无需取反)。一个负数的二进制数反码形式为其绝对值部分按位取反(即符号位不变,其余各位按位取反)。同原码-{表}-示一样,0的反码表示形式也有两种:00000000(+0)与11111111([[-0|−0−0]])。
举例来说,原码10101011(-43)的反码形式为11010100(−43)11010100(−43)。有符号数用反码-{表}-示的范围为−−(2<sup>N−1N−1</sup>−1−1)到(2<sup>N−1N−1</sup>−1−1),以及+/−0−0。传统的表示为−127−127<sub>10</sub>到+127<sub>10</sub>,以及00000000(+0)或者11111111(−0)11111111(−0)。
对两个反码-{表}-示形式的数字做加法,首先需要进行常规的二进制加法,但还需要在和的基础上加上[[进位标志|进位]]。为什么必须这样呢?来看下面这个−1−1加上+2的例子。
<pre style="width:35em;">
二进制 十进制
反码这种数字表示系统通常出现在老式的计算机中;[[PDP-1]],[[CDC 160A]],[[UNIVAC 1100/2200系列]]以及其它的一些电脑都使用反码算术。
关于[[正字法]](orthography)的评述:这个系统之所以被称作反码(ones' complement)是因为一个正值''x''的反(表示为[[按位非]]''x'')也可以通过0的反码(ones' complement)表示形式(一长串的1,−0)1,−0)减去''x''得到。
[[Internet]]协议[[IPv4]],[[互联网控制消息协议|ICMP]],[[用户数据报协议|UDP]]以及[[传输控制协议|TCP]]都使用同样的16位反码检验和算法。虽然大多数计算机缺少[[补的方法|“循环进位”]]硬件,但是这种额外的复杂性是可以接受的,因为“对于所有位(bit)位置上的错误都是同样敏感的”。<ref>{{cite web
'''补码'''回避了0有多种表示的问题以及循环进位的需要。在补码表示中,负数以位模式表示为正值的反码加1(当作无符号数)。
在补码表示中,只有一个0(00000000)。求一个数的补(无论是负数还是正数)需要反转所有位,然后加1。一对补码整数相加等价于一对[[无符号数]]相加(除了溢出检测,如果能够做到的话)。比如,从旁边的表格可以看出,127与−128−128的补码表示相加就与无符号数127及128相加具有相同的结果。
从一个正数得到其对应负数的补码的简单方法表示如下:
|