以有符号整数或二进制数字表示
零被视为正号
和
1 被视为负号。
例如 :-
1000 0000 0000 0110 = -6
0000 0000 0000 0110 = 6
但在脉冲形式中,1 被视为正,而 0 被视为中性。
--- --- ---
| | | | | |
--------- --- --- ---------
为什么?这背后有什么逻辑吗?
是否可以以相反的方式处理它,即 1 为正号,0 为负号
答案1
您最初的断言并不正确,对于绝大多数使用“二进制补码算法”的常见 CPU 架构来说并非如此。
在 2 的补码运算中,如果高位为 1,则表示负数;但如果高位为 0,则不表示正数。它表示非负。差异很微妙,但很重要。数字可能是零,也可能是正数。
在 2 的补码中,数字刻度如下所示 - 为简单起见,我将使用八位整数:
二进制 有符号 无符号 0111111111127127 01111110126126 ... 00000011 3 3 00000010 2 2 00000001 1 1 00000000 0 0 11111111 -1 255 11111110 -2 254 ... 10000010 -126 130 10000001 -127 129 10000000 -128 128
在这个系统中,要对一个数字取反(算术取反),也就是将其乘以 -1:首先取反所有位,然后加 1。因此,如果我们从 1 开始,然后取反所有位,我们将得到 11111110。加 1,我们得到 11111111。如上所述。请注意,如果我们再次执行此操作,我们将得到 00000001,正如我们应该得到的那样。
计算机使用这个系统是因为它使加法、减法等算术逻辑变得非常简单:相同的逻辑(简单的二进制加法器;你只需添加所有位,包括符号位)适用于有符号数和无符号数。请注意,在该范围内的任何数字上加 1 都会得到正确答案……溢出情况除外:如果你将数字解释为有符号的,则将 1 加到 127 上会得到 -128。但溢出和进位等通常由条件标志或异常捕获。
二进制补码的一个奇怪特点是负数比正数多一个……因为零既不是负数也不是正数。因此,使用带符号的八位,我们可以表示 -128,但不能表示 +128。+127 是最高正数。这不是什么大问题。
一些历史计算机(CDC 3000 和 6000 系列,以及一些旧的 Univac 大型机;我不知道当代的例子)已经使用“一的补码”。在一的补码中,要反转数字,只需翻转位。这会产生与上面几乎相同的比例,只是负数从 -127 变为... -0!没错,在一的补码机器中,有两个零:正零和负零。这使得算术通常更加复杂。负零通常会在某个时候转换为正数。
您可能认为它应该更像“有符号的幅度”,这类似于我们通常写数字的方式。例如 -2 将是 10000002。您会注意到,向其添加 1 并不能为您提供 -1 的正确有符号的幅度表示。相反,它会给出 -3。这使得算术变得更加复杂,这就是为什么它不被使用的原因。
答案2
这其实相当复杂。从某种程度上来说,答案是“因为我们需要某种标准”:如果你开发一个新系统,那么让它以与旧系统相同的方式运行要容易得多,这样你就可以更轻松地与旧系统交互。然而,在某些情况下,还有更深层次的原因。
在本文中,我将假设整数为 8 位。使用不同的位数时,原理应该相同。
电脉冲
这里只有两个值,我们称哪个为“零”,哪个为“一”并不重要。事实上,没有理由称它们为“零”和“一”。例如,USB 使用“J”和“K”,并且一些 USB 设备使用与其他设备相反的约定来实际传输信号。
整数编码
实际上,有几种方法可以对整数进行编码。您在问题中展示的方法称为“带符号的数值”。它与我们在日常生活中写数字的方式非常相似:我们可能有一个减号,然后我们写出数字。在这种情况下,减号(或加号)只是第一位的值。
但是,并非所有数字都是有符号的。如果我要对工厂今天生产的小部件数量进行编码,我想使用无符号数(除非我有时会销毁工厂中的小部件)。在这种情况下,让 表示0000 0110
我当天生产了六个小部件才是合理的。
如果您同时使用有符号数和无符号数,那么如果它们之间的转换尽可能简单就好了。如果在两种情况下相同的位代表相同的数字,则转换会更容易,因此0000 0110
即使我们使用有符号整数,我们也希望表示六。这导致前导1
为负数,前导0
为正数。
二进制补码
但是现在很少有系统真正使用有符号整数。有符号整数有许多问题,包括0000 0000
和1000 0000
表示同一件事(零)。相反,大多数系统使用所谓的“二进制补码”来表示有符号整数。它以相同的方式表示正数(以零为前导,其他位与无符号数相同),但以不同的方式表示负数。对于无符号的八位数,最高有效位是 128 位;对于二进制补码八位数,它是负 128 位。因此,1000 0000
为负 128,1000 0001
为负 128 + 1 = 负 127,一直到1111 1111
,为负一。
这似乎是一种表示有符号整数的奇怪方法,但与更明显的有符号幅度相比,它有许多优点。首先,它解决了我之前提到的零有两种表示方法的问题。其次,您可以使用与添加无符号数相同的电路来添加数字,并且假设没有溢出(即使有溢出,也更容易处理),它将正确运行。有符号幅度则不然。
结论
有很多方法可以表示有符号数; 有符号幅度和二进制补码只是其中两种比较流行的方法。从某种意义上说,使用哪种方法并不重要;理论上,你可以发明你自己的方法(没有列出来)(或者只使用符号位反转的有符号幅度),并制造使用它的整台计算机。但这很可能不是一个好主意,因为如果你想与另一台计算机共享数据,你需要转换成不同的格式。我们最终可能会使用有符号幅度整数作为我们的标准(就像我们在浮点数字),那么对于大多数新计算机来说,最佳选择可能就是做同样的事情。但是,这种选择并不是完全随意的,有充分的理由让正整数使用前导零而不是前导一(例如与无符号数一致)。
答案3
这是一个任意的标准签整数。查看较小的有符号字节,其中 00000000 到 01111111 被视为正整数,最高位在设置时使它们为负数,范围从 -127 到 127(基数为 10),零编码前导位设置或不设置。相同的位模式还编码未签名数字 0 到 255,因此它只是一个让程序员能够理解其他人工作的标准。参见http://en.wikipedia.org/wiki/Signed_number_representations有关有符号数表示的信息。
你可以发明自己的有符号数标准,但这会导致混乱。在某些语言中,布尔真的被视为 00000001,在其他语言(例如 VB)中则为 10000001,而在其他语言中则是除零以外的任何值。这只是在翻译程序语言时需要警惕的另一个陷阱。