编码
编码不是把数字换一种写法,而是把一个值压进固定宽度的机器状态里。看起来像数学,实际更像协议:哪些状态表示正负,哪些状态被浪费,哪些状态能直接交给加法器。
各编码方案对比
先把几个方案并排看。这个表不是为了背概念,而是为了看出它们的取舍:有的保留直觉,有的保留电路便利,有的服务浮点指数。
| 编码 | 零的个数 | 加法是否直接 | 现在用在哪 |
|---|---|---|---|
| 原码 Sign-Magnitude | 2 | 否 | IEEE 754 符号位 |
| 反码 One’s Complement | 2 | 需要回卷进位 | 几乎废弃 |
| 补码 Two’s Complement | 1 | 是 | CPU 整数运算 |
| 移码 Biased Notation | 1 | 不用于加法 | IEEE 754 指数字段 |
Sign-Magnitude 原码
原码最直观:最高位是符号位,剩下的位是绝对值。它像人在纸上写数,先写正负,再写大小。
+43 = 0_0101011
-43 = 1_0101011
它有两个零。加法也不能直接做,遇到不同符号时需要比较大小,再决定减法方向。
One’s Complement 反码
反码试图让负数进入位运算系统:正数不变,负数把正数的每一位取反。它比原码更接近机器,但还没有完全解决零的问题。
+43 = 00101011
-43 = 11010100
反码加法需要把最高位溢出的进位再加回最低位,这叫 end-around carry。这个规则并不优雅,说明它还没有和二进制加法器完全对齐。
Two’s Complement 补码
补码是现代 CPU 整数的主流,因为它把减法变成了加法。负数等于反码再加一,于是所有整数可以放在一个环里。
+43 = 00101011
-43 = 11010101
它只有一个零。代价是范围不对称:8 位补码可以表示 -128 到 +127。这个不对称不是错误,而是把一个原本浪费给 -0 的状态拿回来用了。
Biased Notation 移码
移码不是为加减法准备的,而是为了比较和排序。它给真实指数加上一个固定偏移,让负指数也能以无符号整数的形式保存。
以 IEEE 754 单精度为例,指数有 8 位,偏移量是 127。真实指数 e 会被存成 e + 127。
IEEE 754 Single Precision
单精度浮点数一共 32 位:1 位符号、8 位指数、23 位尾数。它不是在表示所有小数,而是在固定宽度里保存“数量级 + 有效数字”。
失去的状态去了哪里
每种编码都在用一种方式交换直觉、范围和电路便利。设计一个表示系统时,真正重要的不是把所有状态都填满,而是决定哪些状态值得被保留下来。
结尾
补码最后留下来的不是一个漂亮的数学对象,而是一套可以稳定工作的约定。机器喜欢约定,因为约定能够让下一步变得便宜。