补码之美

在计算机中,为什么 -1 要用补码表示为 1111 ?

首先要了解 CPU 的基本单元 ALU 模块。在 ALU 里,加法是最基本的运算。通过程序,乘法可以转换为加分,除法可以转换为减法。补码表示,则可以让减法直接转换为加法。这样,ALU 核心只需要加法器就好,加法器可以通过集成电路中的晶体管来实现。

要将减法转换为加法,在数学公式里,只要加一个括号即可:

X - Y = X + (-Y)

在 CPU 里,如果想让加法器具备减法功能,核心是负数如何表示。

原码

大自然赐予了我们硅,硅是很稳定的半导体,通过 PN 结等精细工艺,可以做成各种晶体管。在晶体管的世界里,基本状态只有 on 和 off 两种,也就是只有
1 和 0。于是,在计算机里,我们采用二进制来表示整数。

这样,最自然的想法是,对于正整数来说,直接从十进制转换成二进制就好。比如 1 用 0001 来表示,2 用 0010 来表示。

负整数怎么来表示呢?增加一个符号位来表示?比如二进制的最高位为 0 时表示正数,为 1 时则表示负数。

这样,-1 用 1001 表示,-2 用 1010 表示。这就是原码的概念。

在原码的表示里:

1 - 1 = 1 + (-1) = 0001 + 1001 = 1010 = -2

显然,原码表示法,不能把减法变成加法,悲催。

补码

据说,所有科学问题,最后都是数学问题,而所有数学问题,最后都离不开哲学。

哲学太深奥了,我们来看看从数学上,如何把 X + (-Y) 转换成二进制相加。

我们希望有某种表示方法,使得 1 + (-1) = 0000 现在 1 用 0001 来表示,-1 应该怎么表示?

-1 = 0000 - 0001
    = 10000 - 0001  (高位借一)
    = (1111 + 0001) - 0001
    = (1111 - 0001) + 0001(第一步:取反)
    = 1110 + 0001(第二步:加一)
    = 1111

也就是说,如果 -1 用 1111 来表示,则 1 + (-1) 的二进制表示通过加法就能进行减法操作,达成了我们最初的目的。

进一步,针对所有负整数:

-Y = 0000 - Y
     = (1111 + 1 ) - Y
     = (1111 - Y) + 1   将正整数 Y 的二进制先取反、再加一

整数转换成二进制后,先取反,再加一,这就是负整数的补码表示。正整数的补码跟原码一样。

到此为止,补码的前世今生就说完了,但还有些有意思的事情。

简单之美

可以说,补码的出现,是为了能让 ALU 在设计时更简单:只需要加法电路就好,不需要减法电路。追求简单,极致的简单,这能给性能、工业化等带来很大价值。

再从数学上来看,整数遵循一些很容易被我们忽略的重要规律:

  1. 数轴上,左边的数永远小于右边的数。比如 -8 < -2 < 0 < 3 < 5
  2. 数轴上,只有一个零。
  3. 相邻整数之间相差一。

来看补码表示:

    -8      -7         -6        -5        -4        -3       -2      -1       0          1         2        3         4        5         6         7
1000 | 1001 |  1010 | 1011 | 1100 | 1101 | 1110 | 1111 | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111
  1. 只看负数的补码表示,明显 1000 < 1001,补码表示下,左边的负数很自然小于右边的负数。
  2. 很明显只有一个零,就是 0000,不存在 -0 跟 0 的表示不一样。
  3. 再看相邻整数之间,左边的整数加一,就是右边的整数,包括 1111 + 1 = 0000 。

初看补码,有些怪异、不直观,但在二进制的世界里,补码是如此自然。第一个想出用补码来表示整数的人,真是个天才啊。

(完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值