补码运算 补码的本质是什么?

文章目录

一、从时钟问题开始:模运算的每一步

1.1 减法与"绕圈"的等价性

问题:一个只有 1 到 12 的时钟,现在指向 4 点,如何让它指向 1 点?

  • 减法(逆时针) :直接计算 4 - 3 = 1

  • 加法(顺时针) :尝试 4 + 9 = 13。但在钟面上,13 点和 1 点是同一个位置。

为什么是 9?

因为时钟系统是"每 12 个数一循环",这叫做模 12 系统 。在模 12 系统中,-3的效果和 +9等价的。因为:

9=12−3

计算验证

  1. 4 + 9 = 13

  2. 13在钟面上的位置 = 13除以 12的余数 = 1

  3. 结果与 4 - 3 = 1相同。

核心公式 :在模 M的系统中,-X等价于 M - X


二、8 位计算机的"时钟"(模 256)

2.1 8 位二进制的范围

8 位二进制能表示 0000000011111111一共 256 个数。无符号理解就是 0 到 255。

计算机的 CPU 寄存器就像一个 8 位的"时钟",当运算结果超出 8 位(大于 255 或小于 0),多出来的位会被丢弃 。这本质上就是自动取模运算,其模数 M=28=256。

例如,255 + 1 = 256,二进制是 1 0000 0000,但寄存器只保留低 8 位 0000 0000,结果又回到了 0,就像时钟从 12 点走到了 1 点。

2.2 用加法实现减法:一个完整例子

我们想计算 5 - 3

  • 普通减法5 - 3 = 2

  • 补码思想 :在模 256 系统中,-3等价于 256 - 3 = 253。所以,计算 5 - 3可以转化为计算 5 + 253

步骤 1:计算 253

253=256−3

步骤 2:将 5 和 253 写成二进制

  • 5的二进制:0000 0101(2^2=4, 2^0=1, 4+1=5)

  • 253的二进制:我们可以计算,也可以从定义出发:

    • 256 的二进制是 1 0000 0000(9 位)

    • 3的二进制是 0000 0011

    • 256 - 3 = 253的二进制计算:

      复制代码
      1 0000 0000  (256)
      -   0000 0011  (3)
      --------------
          1111 1101  (253)

      计算过程:

      1. 从最低位开始,0 减 1 不够,向高位借 1。由于高位是 0,一直借到最高位(第九位)。

      2. 借位后,最低位变为 10(2) - 1= 1

      3. 依次计算,得到低 8 位为 1111 1101。这正是 253 的二进制。

步骤 3:执行加法并丢弃进位

复制代码
0000 0101  (5)
+ 1111 1101  (253)
-----------------
1 0000 0010  (258)
  1. 从最低位相加:

    • 1 + 1 = 0, 进位 1

    • 0 + 0 + 进位1 = 1

    • 1 + 1 = 0, 进位 1

    • 0 + 1 + 进位1 = 0, 进位 1

    • 0 + 1 + 进位1 = 0, 进位 1

    • 0 + 1 + 进位1 = 0, 进位 1

    • 0 + 1 + 进位1 = 0, 进位 1

    • 0 + 1 + 进位1 = 0, 进位 1

  2. 最终得到 9 位结果 1 0000 0010,即十进制 258。

  3. 由于是 8 位系统,我们丢弃最高位的 1(即 256),只保留低 8 位 0000 0010

  4. 0000 0010正是十进制的 2

✅ 我们用加法 5 + 253完美模拟了减法 5 - 3的结果。

结论 :在 8 位计算机中,我们用二进制数 1111 1101(无符号 253)来表示 -3 。这就是 -3 的补码

补码公式

对于一个 n 位的二进制系统,负数 -X的补码等于 2^n - X的无符号二进制表示。


三、"取反加一"的来历:一步一步推导

对于 8 位系统,n=8,我们要表示 -X

从定义出发

补码(−X)=28−X

关键推导

28−X=(28−1)−X+1

步骤 1:计算 2^8 - 1

  • 28=256,二进制是 1 0000 0000

  • 减 1 得 255,二进制是 1111 1111(8 个 1)。

步骤 2:计算 (2^8 - 1) - X

以 X = 3 (0000 0011) 为例:

复制代码
1111 1111  (255)
- 0000 0011  (3)
--------------
  1111 1100

逐位计算(二进制减法,借位法):

  1. 最低位:1 - 1 = 0

  2. 次低位:1 - 1 = 0

  3. 其余位:1 - 0 = 1

    得到一个非常重要的观察:255 - X的结果,就是把 X的二进制数 每一位取反 (1 变 0,0 变 1)。3(0000 0011) 取反后正好是 1111 1100,即 252。这个"取反"后的结果称为 反码

步骤 3:最后再加 1

  • (28−1)−X=255−3=252,二进制 1111 1100

  • 再加 1:1111 1100 + 1 = 1111 1101

  • 结果 1111 1101正是我们之前用 28−3算出来的 253 的二进制,也就是 -3 的补码。

✅ 我们证明了:

补码 = 对原数进行"按位取反,再加 1"

这个"取反加一"是计算补码的快捷算法,它的本质是公式 2n−X的数学推导。


四、从补码反推十进制:最高位的"负数权重"

已知一个 8 位补码 1000 0011,如何知道它代表哪个十进制数?

核心公式(8位为例):

一个 8 位补码二进制数 b7​b6​b5​b4​b3​b2​b1​b0​的十进制值 V为:

V=−b7​×27+b6​×26+b5​×25+b4​×24+b3​×23+b2​×22+b1​×21+b0​×20

解释 :最高位(符号位)的权重是 负的​ 27=−128,其余位的权重是正的。

例子 :计算 1000 0011的十进制值。

  1. 分解每一位及其权重:

    • b7​=1→ −1×128=−128

    • b6​=0→ 0×64=0

    • b5​=0→ 0×32=0

    • b4​=0→ 0×16=0

    • b3​=0→ 0×8=0

    • b2​=0→ 0×4=0

    • b1​=1→ 1×2=2

    • b0​=1→ 1×1=1

  2. 将所有项相加:

    V=(−128)+0+0+0+0+0+2+1=−125

公式为什么成立?推导

假设一个 8 位补码 b7...b0对应的无符号数是 U=b7​×128+b6​×64+...+b0​×1。

根据补码定义:

  • 如果它是正数(b7=0),其值 V=U。

  • 如果它是负数(b7=1),其值 V=U−256(因为补码是 28+V=U)。

当 b7=1 时

V=(1×128+b6​×64+...+b0​×1)−256

V=128−256+b6​×64+...+b0​×1

V=−128+b6​×64+...+b0​×1

这正是我们的"负权重公式"。


五、完整示例:从 -13 到补码,再转回来

5.1 求 -13 的 8 位补码

方法一:用公式 28−13

  1. 256−13=243

  2. 将 243 转换为 8 位二进制(短除法):

    • 243 ÷ 2 = 121 ... 1​ ← 最低位 (LSB)

    • 121 ÷ 2 = 60 ... 1

    • 60 ÷ 2 = 30 ... 0

    • 30 ÷ 2 = 15 ... 0

    • 15 ÷ 2 = 7 ... 1

    • 7 ÷ 2 = 3 ... 1

    • 3 ÷ 2 = 1 ... 1

    • 1 ÷ 2 = 0 ... 1​ ← 最高位 (MSB)

    • 从下往上(最后到最先)读出结果:1111 0011

      ✅ 所以,-13 的补码是 1111 0011

方法二:用"取反加一"验证

  1. +13 的二进制:0000 1101(8+4+1=13)

  2. 取反 :得到 1111 0010

  3. 加 1

    复制代码
    1111 0010
    + 0000 0001
    ------------
      1111 0011

    ✅ 与公式法结果一致。

5.2 从补码 1111 0011还原为十进制

使用负权重公式

  1. 位与权重对应:

    • b7=1 → −128

    • b6=1 → +64

    • b5=1 → +32

    • b4=1 → +16

    • b3=0 → +0

    • b2=0 → +0

    • b1=1 → +2

    • b0=1 → +1

  2. 逐步相加:

    • −128+64=−64

    • −64+32=−32

    • −32+16=−16

    • −16+0=−16

    • −16+0=−16

    • −16+2=−14

    • −14+1=−13

      ✅ 得到结果 -13。


六、核心总结

步骤 操作 具体计算与意义
1 确定模数 M 对于 n 位系统,M=2n。这是"时钟"的总刻度。
2 定义补码 负数 -X的补码是 M - X的无符号二进制形式。
3 快捷算法 补码 = 对 X 的原码"取反 (得到反码)",再"加 1"。这是从公式推导而来。
4 用加法代替减法 计算 A - B时,CPU 实际上计算 A + (M - B),并丢弃结果的最高位进位。
5 补码转十进制 使用公式:V=−bn−1​×2n−1+∑i=0n−2​bi​×2i。符号位的权重是负的。

补码的精妙之处

  1. 统一了加减法:CPU 只需要一个加法器,就能处理所有有符号数的加减运算。

  2. 零的唯一性0000 0000表示 0,1000 0000表示 -128,没有"正零"和"负零"的歧义。

  3. 范围对称:8 位补码范围是 -128 到 +127。负数比正数多一个(-128)。