原码, 反码, 补码 详解
计算机里一个整数可以用原码、反码、补码三种方式编码。搞清楚它们怎么算、机器为什么最终用补码,以及为什么补码加法能完成原码减法,对理解底层运算很有帮助。
一、机器数和真值
一个数在计算机中的二进制表示叫做机器数。机器数带符号:最高位存放符号,正数为 0,负数为 1。字长 8 位时,+3 是 00000011,-3 是 10000011,这两个就是机器数。
因为第一位是符号位,机器数的形式值不等于真正的数值。例如有符号数 10000011,最高位 1 代表负,真值是 -3,而不是把整串当成无符号数得到的 131。带符号位的机器数对应的真正数值,叫做机器数的真值:0000 0001 的真值 = +1,1000 0001 的真值 = -1。
二、原码、反码、补码
原码、反码、补码是机器存储一个具体数字的编码方式。
| 编码 | 正数 | 负数 | 例子(-1) |
|---|---|---|---|
| 原码 | 符号位 + 绝对值 | 符号位 1 + 绝对值 | 1000 0001 |
| 反码 | 等于原码 | 符号位不变,其余取反 | 1111 1110 |
| 补码 | 等于原码 | 反码末位 +1 | 1111 1111 |
8 位原码的取值范围是 [1111 1111, 0111 1111],即 [-127, 127]。原码最贴近人脑;负数的反码、补码通常要先转回原码才能看出数值。
三、为何机器用补码
正数三种编码相同,不必多解释。负数则完全不同。人脑看见符号位就知道该加还是该减,但让计算机辨别符号位会让电路复杂。减法可以改成「加上一个负数」:1 – 1 = 1 + (-1)。如果符号位也参与运算,机器就可以只做加法。
用原码算 1 – 1:
用反码:真值部分对了,却得到 -0,并且 0 有 [0000 0000] 和 [1000 0000] 两个编码。补码解决 0 的符号问题:
[1000 0000]补 表示 -128,它没有对应的原码和反码。因此 8 位原码/反码范围是 [-127, +127],补码是 [-128, 127]。32 位 int 用补码时范围为 [-2^31, 2^31-1]。
四、怎么求补码,以及 ~6 为什么是 -7
正数的原码、反码、补码都是它本身。负数 -15 的计算:
Java 中 int 是 4 字节。6 在机器里是 0000…0110,按位取反 ~6 得到 1111…1001。最高位为 1,这是补码表示的负数。还原原码:符号位不变、其余取反得 1000…0110,再末位加 1 得 1000…0111,即 -7。
原文出处:原码, 反码, 补码 详解
一句话总结:机器只用补码做加减,这样 0 只有一种编码,还能多表示一个最小值;~n 等于 -(n+1)。
转载请注明来源:原码, 反码, 补码 详解






