有符号整数的三种编码方式:原码、反码和补码

在计算机中,原码、反码、补码 是用于表示有符号整数的三种编码方式,主要用于解决二进制数的 正负表示加减运算 问题。它们的核心区别在于 符号位的处理负数的表示方法


原码(Sign-Magnitude)

定义

  • 最高位(最左边的一位)表示符号:
    • 0 表示正数(如 +5
    • 1 表示负数(如 -5
  • 其余位表示数值的绝对值。

示例(8位二进制)

十进制 原码表示(8位)
+5 0000 0101
-5 1000 0101

特点

直观:和人类书写习惯一致(正负号+数值)。
问题

  1. +0-0 不唯一
    • +0 = 0000 0000
    • -0 = 1000 0000(计算机无法区分)
  2. 加减运算复杂
    • 需要额外判断符号位,硬件实现麻烦。

反码(Ones’ Complement)

定义

  • 正数:和原码相同。
  • 负数:在原码基础上,符号位不变,数值位取反0110)。

示例(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 的补码

  1. +5 原码 = 0000 0101
  2. 取反 = 1111 1010(反码)
  3. +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(溢出位舍弃

从上表可以看出,如果使用补码进行计算,就可以正常的进行加法算术运算了。

特点

解决所有问题

  1. +0-0 统一

    • +0 = 0000 0000
    • -0 :原码 1000 0000 → 反码 1111 1111 → 补码 0000 0000(和 +0 相同)。
  2. 加减法直接运算

    • 5 + (-3) = 0000 0101 + 1111 1101 = 0000 00102,正确)。
  3. 表示范围更大

    • 8位补码范围:-1281000 0000)~ +1270111 1111),比原码/反码多一个数(-128)。

那么至此,总结两个非常重要的结论:

  1. 正数的原码反码补码是一致的,负数的反码是原码除符号位取反,补码是反码+1。
  2. 计算机中有符号整数的存储方式都是以补码的形式存储的,运算也是以补码的形式计算的。

三种编码对比(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

为什么计算机使用补码

  1. 统一 +0-0,避免歧义。
  2. 加减法可以直接运算,无需额外判断符号。
  3. 硬件实现简单,CPU 只需加法器,无需额外电路。
  4. 表示范围更大(如 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 问题,运算简单 负数计算稍复杂 现代计算机标准

补码是计算机存储和处理有符号整数的 最优方案,理解它对于学习 计算机组成原理、编程(如整数溢出)、逆向工程 都至关重要!