谈补码
从补码的定义出发,解释反码加一、符号位、整数范围、符号扩展以及算术右移这些看似零散的有符号整数问题。
这是一篇从早期博客迁移来的 PDF 文章。原文围绕“补码是什么”展开,不满足于把补码记成“反码加一”,而是试图从有限位宽整数、溢出截断和负数编码的角度解释补码为什么会被这样定义。
长摘要:
文章先用一个历史化的视角说明补码的动机:如果负数也能被编码成某种二进制形式,计算机就可以用同一个加法器完成加法和减法,而不必再单独设计减法器。在有限位宽下,溢出会丢弃高位,这使得一个数和它的补码相加后可以得到被截断为零的结果;由此可以推导出“补码等于反码加一”。
接着,文章讨论有符号整数的符号位为什么通常用 0 表示非负、1 表示负数。关键点在于把最高位解释为负权重之后,补码到十进制的转换可以写成统一的公式;符号位不只是一个标记,而是实际参与数值计算的一位。
最后,文章用补码解释几个常见但容易被机械记忆的问题:为什么 32 位有符号整数范围是 [-2^31, 2^31 - 1],为什么最小值的绝对值比最大值大一,为什么整数扩展分为零扩展和符号扩展,以及为什么右移需要区分逻辑右移和算术右移。这些现象都可以回到同一个原则:扩展或移位后,二进制序列按补码解释出来的数值应当保持一致。