有符号整数的三种编码方式:原码、反码和补码
在计算机中,原码、反码、补码 是用于表示有符号整数的三种编码方式,主要用于解决二进制数的 正负表示 和 加减运算 问题。它们的核心区别在于 符号位的处理 和 负数的表示方法。
原码(Sign-Magnitude)
定义
- 最高位(最左边的一位)表示符号:
0
表示正数(如+5
)1
表示负数(如-5
)
- 其余位表示数值的绝对值。
示例(8位二进制)
十进制 | 原码表示(8位) |
---|---|
+5 | 0000 0101 |
-5 | 1000 0101 |
特点
✅ 直观:和人类书写习惯一致(正负号+数值)。
❌ 问题:
+0
和-0
不唯一:+0
=0000 0000
-0
=1000 0000
(计算机无法区分)
- 加减运算复杂:
- 需要额外判断符号位,硬件实现麻烦。
反码(Ones’ Complement)
定义
- 正数:和原码相同。
- 负数:在原码基础上,符号位不变,数值位取反(
0
→1
,1
→0
)。
示例(8位二进制)
十进制 | 反码表示(8位) |
---|---|
+5 | 0000 0101 |
-5 | 1111 1010 |
十进制运算 | 反码计算 | 反码计算结果(十进制) |
---|---|---|
1 +(-1)= 0 | [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 | -0 |
1 +(-2)= -1 | [0000 0001]反 + [1111 1101]反 = [1111 1110]反 = [1000 0001]原 | -1 |
-1 +(2)= 1 | [1111 1110]反 + [0000 0010]反 = [0000 0000]反(溢出) = [0000 0000]原 | 0(溢出归0) |
从上表可以看出,如果用反码直接进行计算,虽然有所改善,但仍有问题,所以计算机中的运算也不能直接用反码。
特点
仍然存在 +0
和 -0
问题
+0
=0000 0000
-0
=1111 1111
(仍然无意义)
运算仍需调整:
- 加减法后可能需要 “循环进位”(如
1 + (-1)
=0000 0001
+1111 1110
=1111 1111
(-0
),需要额外加1
修正)。
补码(Two’s Complement)⭐(现代计算机标准)
定义
- 正数:和原码相同。
- 负数:在反码基础上 +1(即
原码取反 + 1
)。
示例(8位二进制)
十进制 | 补码表示(8位) |
---|---|
+5 | 0000 0101 |
-5 | 1111 1011 |
计算 -5
的补码
+5
原码 =0000 0101
- 取反 =
1111 1010
(反码) - +1 =
1111 1011
(补码)
举个例子,如果是8位的二进制数:
[+1] = [0000 0001]原 = [0000 0001]反 = [0000 0001]补
[-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]补
[-2] = [1000 0010]原 = [1111 1101]反 = [1111 1110]补
十进制运算 | 补码计算 | 补码计算结果(十进制) |
---|---|---|
1 +(-1)= 0 | [0000 0001]补 + [1111 1111]补 = [0000 0000]补 = [0000 0000]原 | 0(溢出位舍弃) |
1 +(-2)= -1 | [0000 0001]补 + [1111 1110]补 = [1111 1111]补 = [1111 1110]反 = [1000 0001]原 | -1 |
-1 +(2)= 1 | [1111 1111]补 + [0000 0010]补 = [0000 0001]补 = [0000 0001]原 | 1(溢出位舍弃) |
从上表可以看出,如果使用补码进行计算,就可以正常的进行加法算术运算了。
特点
✅ 解决所有问题:
+0
和-0
统一:+0
=0000 0000
-0
:原码1000 0000
→ 反码1111 1111
→ 补码0000 0000
(和+0
相同)。
加减法直接运算:
5 + (-3)
=0000 0101
+1111 1101
=0000 0010
(2
,正确)。
表示范围更大:
- 8位补码范围:
-128
(1000 0000
)~+127
(0111 1111
),比原码/反码多一个数(-128
)。
- 8位补码范围:
那么至此,总结两个非常重要的结论:
- 正数的原码反码补码是一致的,负数的反码是原码除符号位取反,补码是反码+1。
- 计算机中有符号整数的存储方式都是以补码的形式存储的,运算也是以补码的形式计算的。
三种编码对比(8位二进制)
十进制 | 原码 | 反码 | 补码 |
---|---|---|---|
+5 | 0000 0101 |
0000 0101 |
0000 0101 |
-5 | 1000 0101 |
1111 1010 |
1111 1011 |
+0 | 0000 0000 |
0000 0000 |
0000 0000 |
-0 | 1000 0000 |
1111 1111 |
0000 0000 |
-128 | 无法表示 | 无法表示 | 1000 0000 |
为什么计算机使用补码
- 统一
+0
和-0
,避免歧义。- 加减法可以直接运算,无需额外判断符号。
- 硬件实现简单,CPU 只需加法器,无需额外电路。
- 表示范围更大(如 8 位补码可表示
-128
~127
,而原码/反码只能-127
~127
)。
常见问题
补码 1000 0000
代表多少
- 在 8 位补码中,
1000 0000
表示-128
(没有对应的原码/反码)。
补码的运算溢出怎么办
- 例如
127 + 1
=0111 1111
+0000 0001
=1000 0000
(-128
,溢出)。 - CPU 会设置 溢出标志位(OF),由程序员处理。
总结
编码 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
原码 | 直观 | ±0 问题,运算复杂 |
早期计算机(已淘汰) |
反码 | 改进负数表示 | ±0 仍存在,运算需调整 |
过渡方案(基本不用) |
补码 | 无 ±0 问题,运算简单 |
负数计算稍复杂 | 现代计算机标准 |
补码是计算机存储和处理有符号整数的 最优方案,理解它对于学习 计算机组成原理、编程(如整数溢出)、逆向工程 都至关重要!