从历史上看,整数格式可以同时表示 -0 和 +0。 sign-and-magnitude 和 one 的补码 都可以表示 -0 和 +0。事实证明,它们不如 two 的补码 有用,后者赢得了青睐并且在今天无处不在。
二的补码有一些数值特性,使其在硬件中实现起来更好一些,并且有两个零会给程序员带来一些麻烦。 (我听说过诸如帐户余额为 -0 而不是 +0 的错误,导致有人在不应该收到账单时收到了账单。)
浮点使用符号和大小,因此它可以表示 -0 和 +0。由于浮点的性质,二进制补码的算术属性对浮点实现的帮助不大,并且有两个零允许程序员在某些情况下使用一些额外的信息。
因此,整数和浮点格式的选择是出于实用性而非数学必要性。
看整数算法
让我们考虑使用四位在计算机硬件中实现一些整数运算来进行研究。基本上我们要做的第一件事就是实现无符号二进制算术,所以我们设计了一些逻辑门来制作加法器和其他算术单元。所以加法器的输入 0101 和 0011 产生输出 1000。
接下来,我们要处理负数。在写作中,我们通过在前面放一个符号来处理负数,所以我们的第一个想法可能是对位做同样的事情:在前面使用一个位来表示负数。现在我们有了一个符号和大小的表示。 0001 表示 +1,1001 表示 -1。 0010 代表+2,1010 代表-2。 0111 代表+7,1111 代表-7。当然,0000 代表 +0,1000 代表 -0。这是一个想法,然后我们必须实施它。我们已经有了一个加法器,如果我们输入 0010 (2) 和 0011 (3),它会正确输出 0101 (5)。但是,如果我们输入 0011 (3) 和 1001 (-1),它会输出 1100 (-4)。所以我们必须修改它。好吧,这还不错,我们有一个无符号二进制减法单元,所以我们可以查看第一位,如果我们添加一个负数,我们减去而不是加法。这适用于某些操作;对于 0011 和 1001,观察第二个操作数的前导 1 并将 011 和 001 输入减法单元将产生 010 (2),这是正确的。但是,如果我们有 0010 和 1011,将 010 和 011 提供给减法单元可能会产生一些错误指示(它最初是为无符号二进制设计的)或者它可能“包装”并产生 111(因为这样的包装,以及“借用”输出中的“out”位,使减法单元作为减法设计的一部分工作)。无论哪种方式,这对我们的签名号码都是错误的;我们希望 0010 (2) 加上 1011 (-3) 的输出为 1001 (-1)。所以我们必须设计新的算术单元来处理这个问题。也许,当添加混合符号的数量时,他们会找出哪一个的幅度更大,从较大的减去较小的,然后应用较大的符号位。无论如何,我们还有大量工作要做,只是设计加法和减法单元。
另一个建议是,将数字设为负数,反转每一位。这称为一个补码。这很容易理解并且符合否定的概念——只是否定一切。让我们考虑一下它如何影响我们的算术单元。对于 +3 或 -3 与 +2 或 -2 的组合,我们希望得到以下结果:0011 (3) + 0010 (2) = 0101 (5), 0011 (3) + 1101 (-2) = 0001 ( 1)、1100 (-3) + 0010 (2) = 1110 (-1) 和 1100 (-3) + 1101 (-2) = 1010 (-5)。经检查,有一种简单的方法可以调整我们的二进制加法器来完成这项工作:对所有四个位进行加法,就好像它们是无符号二进制一样,如果前导位有进位,则将其加回低位。在无符号二进制中 0011 + 0010 = 0101 没有进位,所以最终输出是 0101。0011 + 1101 = 0000 有进位,所以最终结果是 0001。1100 + 0010 = 1110 没有进位,所以最终结果是 1110 . 1100 + 1101 = 1001 有进位,所以最终结果是 1010。
这很好;我们的补码加法器比符号和幅度加法器更简单。它不需要比较大小,也不需要做减法来处理负数。我们可以让它更便宜并获得更多利润。
然后有人提出了二进制补码的想法。从概念上讲,我们将从 2n 中减去数字,而不是反转每一位,其中 n 是位数。所以 10000 - 0001 = 1111 表示 -1,1110 是 -2,1101 是 -3,以此类推。这对我们的加法器有什么影响?
在无符号二进制中,0010 (2) + 1101 (13) = 1111 (15)。在二进制补码中,0010 (2) + 1101 (-3) = 1111 (-1)。位是一样的!这实际上适用于所有二进制补码;添加无符号数的位模式会产生与添加二进制补码数相同的结果。 我们可以对无符号二进制和二进制补码使用完全相同的逻辑门。太棒了,给那个员工加薪吧。这就是现代硬件所做的;用于加或减二进制补码的算术单元与用于加或减无符号数的算术单元相同。
这就是为什么二进制补码在表示负整数方面胜出的主要原因。它带来了更简单、更容易、更便宜、更快、更高效的计算机。
(无符号加法和补码加法的区别:如何检测溢出。在无符号加法中,如果有高位进位就会发生溢出。在二进制补码加法中,如果有幅度位的最高进位,因此符号进位。加法器单元通常通过以一种或另一种形式报告这两种指示来处理此问题。如果需要,该信息将在以后的指令中进行测试;它不会影响添加本身。)