跳转至

理解计算机中的数制、补码与减法实现

这篇文章的核心始于计算机世界的基本沟通方式——数制。首先,我们需要理解我们日常使用的十进制,它基于“逢十进一”的规则,是我们与世界互动的自然语言。然而,计算机的硬件由无数个微小的开关构成,只能表示“开”和“关”两种状态,这对应着二进制中的 10。二进制是计算机能够直接理解的“母语”,其规则是“逢二进一”。但二进制表示法对于人类来说过于冗长且容易出错(例如,数字 65 写为 01000001),因此引入了十六进制作为一种折中方案。十六进制“逢十六进一”,使用 0-9A-F 共16个符号来表示数值。它的最大优势在于与二进制之间存在着简洁的转换关系:每一位十六进制数恰好可以表示四位二进制数。这使得十六进制成为人类程序员阅读和编写机器码的一种高效、紧凑的表示方式。

在计算机内部,所有数字都以固定长度的二进制形式存储,这种形式被称为机器数。而这个数字在现实世界中的实际值,则被称为真值。要区分一个机器数是正数还是负数,计算机采用了一个简单的约定:查看其最高位,也称为符号位。如果符号位为 0,则该数被解释为正数或零;如果符号位为 1,则被解释为负数。这种设计使得计算机能够用同一种二进制格式来统一表示所有有符号整数。

既然符号位决定了正负,那么一个负数的具体数值是如何确定的呢?现代计算机普遍采用补码表示法。补码的精妙之处在于它统一了加法和减法运算。一个正数的补码就是其自身的二进制表示。而一个负数的补码,可以通过一个简单的两步“咒语”从其对应的正数转换而来:第一步,按位取反(将所有的 0 变成 11 变成 0);第二步,在结果的末位加一。反之,要从一个负数的补码推算出它的真值,也可以使用同样的“咒语”,这揭示了补码运算的对称性。例如,通过对 FFFF FFDFH 进行“按位取反,末位加一”的操作,我们可以得到其对应的正数值 0000 0021H,即33,从而得知 FFFF FFDFH 的真值是 -33。

补码表示法最重要的一个工程意义在于它简化了计算机的算术逻辑单元的设计。在补码体系下,减法运算可以被完全转化为加法运算。计算 x - y 就等同于计算 x + (-y)。在硬件层面,这意味着计算机只需要一套加法器电路就可以同时处理加法和减法,无需为减法设计额外的复杂逻辑。具体的运算流程是:将第一个操作数(被减数 x)的补码与第二个操作数(减数 y)的相反数的补码([-y]补)直接相加。这个过程与我们做普通加法完全一样,只是在处理十六进制时需要注意“逢十六进一”。

在进行补码加法时,尤其是在处理固定位数(如32位或64位)的整数时,会遇到一个现象:最高位的计算可能会产生一个进位。例如,在 FFFF FFDFH + FFFF FFB FH 的计算中,最高位的 F+F+1 会产生一个向更高位的进位 1。在定长整数运算中,这个超出了规定位数的进位会被自然丢弃。这并非错误,而是补码运算体系的内建规则。只要运算结果没有超出该数据类型所能表示的范围(即没有发生溢出),丢弃这个进位后的结果就是正确的。这个特性保证了补码运算在一个封闭的环状系统内正确工作,是计算机底层算术的基础之一。