计算机内部一切数据都以二进制存储。本文整理整数的原码、反码、补码三种表示法,补码的优势,以及加法溢出与判断方法,作为理解 CPU 运算器的基础。
一个二进制数从右往左第 (i) 位(从 0 计)的权值为 (2^i)。例如:
[ (1011)_2 = 1\times2^3 + 0\times2^2 + 1\times2^1 + 1\times2^0 = 11 ]
一个 (n) 位机器数能表示的无符号整数范围为 (0 \sim 2^n-1)。但数值有正负,需要用特定编码表示符号。
以 8 位((n=8))为例,真值 (x) 的三种表示:
符号位 + 数值绝对值。最高位为符号,其余为绝对值二进制。
| 真值 | 原码 |
|---|---|
| +5 | 0000 0101 |
| -5 | 1000 0101 |
正数反码同原码;负数反码 = 原码除符号位外逐位取反。
| 真值 | 原码 | 反码 |
|---|---|---|
| +5 | 0000 0101 | 0000 0101 |
| -5 | 1000 0101 | 1111 1010 |
正数补码同原码;负数补码 = 反码 + 1。
| 真值 | 原码 | 补码 |
|---|---|---|
| +5 | 0000 0101 | 0000 0101 |
| -5 | 1000 0101 | 1111 1011 |
补码的核心优势:将减法统一为加法。对任意 (a)、(b):
[ a - b = a + (-b)_{\text{补}} ]
CPU 只需一个加法器即可同时完成加减法,无需判断符号,硬件大幅简化。
0 唯一表示:(+0) 与 (-0) 的补码都是 0000 0000,消除了歧义。
对 (n) 位补码:
8 位补码范围为 -128 ~ +127。注意 1000 0000 表示 -128,是补码多表示出的一个数(原码/反码没有 -128)。
求负数补码的速记:对负数的原码,从右往左找到第一个 1,该位及右边不变,左边(符号位除外)全部取反。例如 -5 的原码为 1000 0101,从右第一个 1 是第 0 位,左边取反(符号位不变)得 1111 1011,即补码;等价地,对绝对值 0000 0101 逐位取反再加 1 结果相同。
5 + (-3) 补码运算:
+5 = 0000 0101
-3 = 1111 1101
相加: 0000 0101 + 1111 1101 = 1 0000 0010(丢弃最高进位)
结果 = 0000 0010 = +2 ✓关键:结果溢出丢弃最高位进位,得到正确补码。
溢出指运算结果超出机器数可表示范围。判断方法:
0111 1111(127) + 0000 0001(1) = 1000 0000(-128) ❌ 溢出(正+正得负)1111 1011(-5) → 16 位应为 1111 1111 1111 1011,而非补 0。