在计算机的世界里,所有数字都得转换成二进制才能被识别和处理,这些带着符号的二进制数就是机器数。它有两个鲜明的特点,决定了后续各种表示方法的设计逻辑。
第一个特点是符号的数字化。现实中的数字有正有负,可计算机硬件只能识别 0 和 1 两种物理状态。于是人们约定,用最高位的 0 代表正数的 “+” 号,用 1 代表负数的 “-” 号,这一位也被称为符号位。

比如二进制真值 – 011011,对应的机器数就是 1011011,符号位 1 明确了它的负数属性。不过要注意,符号位会占用一位二进制空间,所以机器数的形式值和真正的数值并不完全等同,这个真正的数值就叫机器数的真值。
第二个特点是位数受机器字长限制。计算机设备一次能处理的二进制位数是固定的,这就是机器字长。常见的字长有 8 位、16 位、32 位和 64 位,其中 8 位被称为一个字节,大部分机器的字长都是字节的整数倍。
为了让机器数能顺利进行运算,人们设计了三种核心表示方法,分别是原码、反码和补码,它们各自有着不同的用途和规则。
原码是最直观的一种表示方式,直接把真值的符号转换成对应的数字符号。对于正数来说,原码的形式和真值完全一致;而负数的原码,就是在其绝对值的二进制前面加上符号位 1。
这种表示方法的优势很明显,数值部分就是数字的绝对值,和真值、十进制数之间的转换非常方便,一眼就能看懂大致数值。但它的短板也很突出,加减法运算过程特别复杂。
当两个数相加时,机器得先判断它们的符号是否相同。符号相同才能直接相加,符号不同就需要做减法运算。做减法前还得比较两个数绝对值的大小,用大数减小数后,再确定结果的符号。
更麻烦的是,负数的符号位不能参与运算,得靠单独的线路来确定结果的符号位。这会让电路设计变得十分复杂,既不经济也不实用,于是反码和补码就应运而生。
反码的出现就是为了弥补原码运算的不足。它的规则很简单,对于正数,反码和原码的形式完全一样;而对于负数,反码需要将原码的数值部分每一位都进行反转,0 变 1,1 变 0。
虽然反码在一定程度上简化了运算逻辑,但并没有彻底解决问题,补码的出现才真正实现了减法向加法的转化,这一设计源于同余的数学概念。
我们可以用一个生活中的例子来理解补码的原理。假设现在北京时间是 6 点,有一块手表显示 8 点,快了 2 小时。校准的方法有两种,要么倒拨 2 小时,要么正拨 10 小时。
倒拨对应减法,正拨对应加法,对这块手表来说,减 2 和加 10 的效果是一样的。因为手表最大只能显示 12,18 减 12 后就只剩 6,这里的 12 就是 “模”,10 就是 – 2 对模 12 的补数。
这个原理被应用到计算机中,计算机的模就是其字长对应的计数器容量。如果机器字长为 n 位,模就是 2 的 n 次方。在这样的规则下,A 减 B 的运算,就可以转化为 A 加上 – B 的补数,即 A–B=A+(-B) 补。
补码的具体规则也很清晰,正数的补码和原码、反码一样,保持不变;负数的补码则是在其反码的基础上,给末位加 1。这一设计让负数的符号位也能参与运算,极大简化了电路设计。
需要特别注意的是,正数的原码、反码和补码完全相同,但负数的三种表示形式则各不相同。而且对于符号位为 1 的反码和补码,其符号位后的数字并不直接代表数值大小,需要通过相应的转换才能得到真正的数值。
在如今的计算机系统中,数值一律采用补码来表示和存储。这种方式既解决了原码运算复杂的问题,又能让硬件设计更简洁高效,成为计算机处理数值的核心方式。
从原码的直观到反码的过渡,再到补码的成熟,机器数的表示方法不断优化,背后是人们对运算效率和硬件成本的平衡考量,也正是这些看似简单的设计,支撑起了计算机复杂的数值运算功能。
