补码

加法

2个十进制数字的非正式算法:两个数字中相同位置的数相加,如果结果超过10产生进位,该进位在下一位数相加时加上。直到两个数字的所有位数都加完为止。

考虑十进制的2位数加法,例如:16 + 26。

    1 6
  + 2 6
 -------
    4 2

上例中的加法过程是:

  1. 6+6 得2,产生进位
  2. 1 + 2 + 1 的4,其中最后加1是1步骤的几位,最终结果是 42

减法

2个10进制数字的非正式算法:

  1. 如果被减数大于等于减数,两个数字中相同位置的数相减,如果被减数小于减数,从高位借一位,轮到高位计算时要多减去一个1。直到两个数字的所有位都减完为止。
  2. 如果被减数小于减数,交互减数与被减数的位置进行 1 操作,把结果加一个负号

考虑十进制的2位数减法,例如:16 - 25。

    1 6
  + 2 5
 -------
    - 9

上例中的加法过程是:

  1. 1625小,交换两个数的位置
  2. 56 小产生借位, 15-6 得到 9
  3. 2-1-1 得到0,最后一个 1是借位
  4. 加上负号,最终的结果是 -9

补码

加法需要记录进位,而减法需要记录借位,比较大小,记录符号。这样减法的复杂度就要比较加法高。

减法变加法

注意到16-25=16+(-25),如果-25能够表示成一个正数,那么减法就变成了加法。

2位10进制的整数范围0-99,取一半用来做正数和零,一半做负数,分布如下:

0 - 0
1 - 1
...
49 - 49
50 - -50
51 - -49
...
99 - -1

按照这个分布,-25对应着75,从而得到16-25=16+75=91,再根据上面的正负数的分布91就是-9,完全与16-25=-9吻合。

另外,如果两个数和超过100,只需要减去100就是对应的结果。

这种用正数表示负数的编码方式叫做补码。由于每个负数正好是100减去表示这个负数的正数,所以叫10的补码。而在二进制情况下,就叫2的补码。因为,二进制下10表示十进制的2.

二进制版本

一个6位数的二进制版本,正负数编码:

000000 - 000000
000001 - 000001
...
011111 - 011111
100000 - -100000
...
111111 - -000001

16的二进制010000-25的二进制10011016-15=>010000+100110=110110=>-9。注意到25的二进制是011001,而-25的二进制100110=1000000-011011=111111-011001+000001,恰好是对011001取反加1。

同时,二进制转化成十进制:

111111 = -(1000000 - 111111)
       = -(2^6 - 2^5 - 2^4 - 2^3 - 2^2 - 2^1 - 2^0)
       = -(2^5 - 2^4 - 2^3 - 2^2 - 2^1 - 2^0)
       = -2^5 + 2^4 + 2^3 + 2^2 + 2^1 + 2^0
011111 = 2^4 + 2^3 + 2^2 + 2^1 + 2^0

最高位的转化取负数,其他会取正数,然后求和正好是十进制的数。

这个结果对计算机来说非常有价值,因为计算机组件有一些逻辑门构成,而逻辑门只能处理真假两个值,这正好可以用01来表示,取反,加1都能很方便的用逻辑门来实现,达到了加法和减法统一,简化逻辑电路的设计。

← map 内部实现 GO 内存模型 →
存档 关于