> For the complete documentation index, see [llms.txt](https://s2.shizhz.me/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://s2.shizhz.me/s2e3/2.md).

# 3.2 补码

在算术运算中，加法是最基本的操作，因为其他的运算都可以通过加法来完成。例如减法就是加上一个负数，而乘法与除法可以分别通过加法与减法来实现。

这里需要解决一个问题，就是如何在二进制中表示负数，以便将减法操作变为加法操作，而不是再重新设计一个减法器的电子组件。

&#x20;我们来看一下产生负数的最基本操作：0 - 1:

```
0000...0000
0000...0001
------------
1111...1111
```

不管是多少位的减法运算都可以表示为上述形式，因为需要借位，所以结果中每一位都是1(我们假设最左边依然借了一位过来，只是空间的有限无法展示）。那么如何用一串 1 表示 -1 呢？我们知道对于一个 n 位全是 1 的二进制数字, 其数值是： `2^(n-1) + 2^(n-2) + ... + 2^1 + 2^0`, 该数列的和为 `2^n - 1`, 因此，如果我们将最高位的权值设置为 -1 的话，那么整个二进制数字的值就刚好是 -1, 如下图所示：

![Two's Complement](/files/-MdWI8nmtQXCr2wAPHYO)

我们来验证一下使用这种方式对整数进行编码时，能否用加法规则完成减法运算：

| 1 - 2 = -1                           | -1 - 1 = -2                             | 2 - 1 = 1                            | 1 - 1 = 0                            |
| ------------------------------------ | --------------------------------------- | ------------------------------------ | ------------------------------------ |
| <p>   000…0001</p><p>+111...1110</p> | <p>   111...1111</p><p> +111...1111</p> | <p>   000…0010</p><p>+111...1111</p> | <p>   000…0001</p><p>+111...1111</p> |
| 111…1111                             | 1111…1110                               | 1000…0001                            | 1000…0000                            |

表格后三列的结果中最高位产生了进位，在现实系统中会因为溢出而被丢弃，因此忽略后三列的最高位后，各列的实际结果为：

1. 111…1111 = -1
2. 111…1110 = -2
3. 000…0001 = 1
4. 000…0000 = 0

所有的运算与预期结果完全一致！

这种对数字进行编码的方式叫补码（2’s complement），补码的优点在于我们可以使用同一套计算规则完成加法、减法两种运算，这样所有的算术运算，包括乘法、除法以及开平方根等，都可以使用加法来完成了。这意味着理论上仅仅通过全加器，使用补码对数字进行编码，就可以搭建出具备完整计算能力的计算机。

补码让加法器成为了二进制世界中算术运算的基础积木。
