补码系统设计的数学表达

213 阅读2分钟

补码(Two's Complement)是计算机中表示有符号整数的标准方式,其设计目标是:

  1. 统一加减法运算:让正数和负数的加法直接用硬件加法器处理,无需额外的减法逻辑。

  2. 避免零的歧义:确保零只有一种表示(而不是正零和负零)。

  3. 最大化表示范围:在固定位数下尽可能多地表示不同数值。

基于这种设计,能简化硬件电路地实现,只需寄存器、NOT 门(取反)、加法器(加 1)、ALU(算术逻辑单元)即可实现计算。

基于补码系统的设计目标,可以得到补码系统的数学目标:

  1. 无缝加法:正数和负数的加法应直接用二进制加法,不需要额外处理符号或绝对值。
  2. 单一 0 表示:0 只有一个二进制表示,避免 +0 和 -0 的歧义。
  3. 最大范围:在 n 位中表示尽可能多的数值(共 2n2^n 个)。
  4. 循环性:数值形成一个“模运算”循环,溢出时自然绕回。

因为设计出了“负数的补码等于其对应的正数取反加一后的值”这一定义,“取反加 1”正是为了实现上面的数学目标的数学操作。

补码系统中,正数和零的表示直接就是其二进制值,负数的表示是将其对应的正数的二进制值全部位取反后加 1。数学上,“取反加一”可以用公式表达,假设 x>0x > 0,令 x 的二进制表示为 B(x)B(x) ,长度为 n 位,取反得到 B(x)\overline{B(x)},即每一位翻转。负数 -x 的补码表示为:

B(x)=B(x)+1B(-x) = \overline{B(x)} + 1

更精确地,B(x)\overline{B(x)} 的值是 (2n1x)(2^n - 1 - x)(因为取反后,1 变 0,0 变 1,相当于用最大值减去 x )。所以:

B(x)=(2n1x)+1=2nxB(-x) = (2^n - 1 - x) + 1 = 2^n - x

从数学上看,“取反加 1”确保了负数和正数在加法运算中行为正确,并且满足补码的循环性质。下面对其进行数学分析:

  1. 实现加法的一致性

补码的目标是让 x+(x)=0x + (-x) = 0,即在补码上的计算行为要和原码相同。正数 xx 的二进制是 B(x)=xB(x) = x,负数 x-x 的补码是 B(x)=2nxB(-x) = 2^n - x。相加:

B(x)+B(x)=x+(2nx)=2nB(x) + B(-x) = x + (2^n - x) = 2^n

nn 位二进制中,2n2^n 是一个溢出,2n=10000...00002^n = 1 0000 ... 0000(第 n+1n+1 位是 1,后面 nn 位是 0),nn 位寄存器只保留低 nn 位,结果是 0000...0000=00000 ... 0000 = 0。所以x+(x)=0x + (-x) = 0 成立,这是“取反加 1”的直接结果。

  1. 实现循环性质(模运算)

补码系统本质上是对 2n2^n 取模的运算,任何加法结果超过 2n2^n,会减去 2n2^n(溢出丢弃),负数 x-x 表示为 2nx2^n - x,正好是模 2n2^n 下的等价值:

x2nx(mod2n)-x \equiv 2^n - x \pmod{2^n}

这种循环靠 2nx2^n - x 实现,而“取反加 1”正好计算出 2nx2^n - x

  1. 单一零表示

x=0x = 0,取反:1111...1111=2n11111 ... 1111 = 2^n - 1,加 1:2n1+1=2n2^n - 1 + 1 = 2^n,模 2n2^n 后是 0。所以,B(0)=B(0)B(-0) = B(0),零只有一种表示。

“取反”计算 2n1x2^n - 1 - x,加 1 变成 2nx2^n - x,这些都是简单的位操作,所以在硬件上只需实现反转器和加法器。

nn 位补码表示 [2n1,2n11][-2^{n-1}, 2^{n-1} - 1],正好 2n2^n 个值,无浪费。如果使用原码,+0 和 -0 都表示 0 ,将浪费一个位置。

补码系统 就像一个圆环,数值在 [0,2n1][0, 2^n - 1]​ 内循环。当计算 x+(2nx)=2nx + (2^n - x) = 2^n2n2^n 超出 nn 位寄存器的范围(最大值是 2n12^n - 1)。硬件自动丢弃溢出位:2n=10000...00002^n = 1 0000 ... 0000(第 n+1n+1 位为 1),低 nn 位是 0000...0000=00000 ... 0000 = 0。硬件不需要特殊逻辑,加法溢出自动归零。如果是原码计算,x 和 -x 的原码相加需要特殊的硬件处理逻辑。

2nx2^n - x 让数值形成圆环,溢出自动绕回:

2n11+1=2n1=2n2n1=2n12^{n-1} - 1 + 1 = 2^{n-1} = 2^{n} - 2^{n-1} = -2^{n-1}
2n11=2n2n11=2n11-2^{n-1} - 1 = 2^{n} - 2^{n-1} - 1 = 2^{n-1} - 1

硬件进行补码计算之后,如果计算的结果是负数,只要对计算结果再次进行“取反加一”的操作,就可以得到其绝对值,再加上符号判断,即可得出正确实际结果。其数学原理在于:负数 x-x 的补码是 2nx2^n - x,对 2nx2^n - x 取反加 1:

2nx+1=(x1)+1=x\overline{2^n - x} + 1 = (x - 1) + 1 = x

逆转了生成补码的过程(B(x)=B(x)+1B(-x) = \overline{B(x)} + 1)。

补码系统的核心思想是设计一套机制,将数学上的有符号整数范围 [2n1,2n11][-2^{n-1}, 2^{n-1} - 1] 映射到无符号整数范围 [0,2n1][0, 2^n - 1]。补码的核心是设计一种“编码”,让负数、正数在二进制世界里用统一的规则运算,结果和数学一致。

数学表达

映射规则

  • 正数和零x0x \geq 0):

    • 直接用二进制表示,最高位为 0。
    • 映射:B(x)=xB(x) = x
    • 范围:[0,2n11][0, 2^{n-1} - 1],例如 [0,2311]=[0,2,147,483,647][0, 2^{31} - 1] = [0, 2,147,483,647]
  • 负数x<0x < 0):

    • 负数 x-x(其中 x>0x > 0)映射为:

      B(x)=2nxB(-x) = 2^n - x
    • 范围:[2n1,1][-2^{n-1}, -1]

      • 最小值 2n1-2^{n-1},例如:

        B(231)=232231=231=10000000...0000B(-2^{31}) = 2^{32} - 2^{31} = 2^{31} = 1000 0000 ... 0000
      • 次小值 2n1+1-2^{n-1} + 1

        B(231+1)=232(2311)=231+1=10000000...0001B(-2^{31} + 1) = 2^{32} - (2^{31} - 1) = 2^{31} + 1 = 1000 0000 ... 0001
      • 直到 1-1

        B(1)=2321=11111111...1111B(-1) = 2^{32} - 1 = 1111 1111 ... 1111
  • 结果

    • 正数和零占用 [0,2n11][0, 2^{n-1} - 1]
      • 二进制:0000...00000000 ... 00000111...11110111 ... 1111
    • 负数占用 [2n1,2n1][2^{n-1}, 2^n - 1]
      • 二进制:1000...00001000 ... 00001111...11111111 ... 1111
    • 整个范围正好覆盖 [0,2n1][0, 2^n - 1],共 2n2^n 个值,无浪费。

数学公式

  • 对于任意有符号整数 k[2n1,2n11]k \in [-2^{n-1}, 2^{n-1} - 1]

    • 如果 k0k \geq 0

      B(k)=kB(k) = k
    • 如果 k<0k < 0

      B(k)=2n+kB(k) = 2^n + k
      • 因为 k=xk = -xx>0x > 0),所以:
        B(x)=2nx=2n+(x)B(-x) = 2^n - x = 2^n + (-x)
  • 这一映射确保:

    • 每个有符号整数 kk 对应唯一的无符号值 B(k)[0,2n1]B(k) \in [0, 2^n - 1]
    • 反过来,每个无符号值 u[0,2n1]u \in [0, 2^n - 1] 对应一个有符号整数。

计算行为一致性

补码的映射不仅覆盖了范围,还保证了运算(特别是加法、减法)在无符号二进制下的结果与有符号整数的数学运算一致。

加法一致性

  • 关键目标x+(x)=0x + (-x) = 0

  • 补码中:

    • 正数:B(x)=xB(x) = x

    • 负数:B(x)=2nxB(-x) = 2^n - x

    • 相加:

      B(x)+B(x)=x+(2nx)=2nB(x) + B(-x) = x + (2^n - x) = 2^n
    • nn 位硬件中:

      • 2n=10000...00002^n = 1 0000 ... 0000(第 n+1n+1 位为 1)。
      • 寄存器只保留低 nn 位:0000...0000=00000 ... 0000 = 0
    • 2n2^n 视角:

      2n0(mod2n)2^n \equiv 0 \pmod{2^n}
      • 所以:
        x+(2nx)0(mod2n)x + (2^n - x) \equiv 0 \pmod{2^n}
  • 任意加法

    • 对于任意 a,b[2n1,2n11]a, b \in [-2^{n-1}, 2^{n-1} - 1]

      • 计算 a+ba + b,结果 ss

      • 补码映射:

        B(a)+B(b)mod2n=B(s)B(a) + B(b) \mod 2^n = B(s)
      • 如果 ss 在范围内,结果正确;如果溢出,模 2n2^n 保证循环性。

    • 公式推导

      • B(a)B(a)B(b)B(b) 的定义: B(a)=amod2n,B(b)=bmod2nB(a) = a \mod 2^n, \quad B(b) = b \mod 2^n
      • 硬件加法: S=(B(a)+B(b))mod2nS = (B(a) + B(b)) \mod 2^n
      • 数学目标: S=B(a+b)S = B(a + b)

      关键是模 2n2^n 的性质:

      • 对于任意整数 kkB(k)=kmod2n(adjusted to [2n1,2n11])B(k) = k \mod 2^n \quad (\text{adjusted to } [-2^{n-1}, 2^{n-1} - 1])
      • 加法: a+bmod2n=(B(a)+B(b))mod2na + b \mod 2^n = (B(a) + B(b)) \mod 2^n

      无溢出

      • 如果 2n1a+b2n11-2^{n-1} \leq a + b \leq 2^{n-1} - 1

        S=a+b(if a+b0)S = a + b \quad (\text{if } a + b \geq 0)
        S=2n+(a+b)(if a+b<0)S = 2^n + (a + b) \quad (\text{if } a + b < 0)
        • 两者都等于 B(a+b)B(a + b)

      溢出

      • 如果a+b>2n11a + b > 2^{n-1} - 1(正溢出):

        a+b=2n+(a+b2n)a + b = 2^n + (a + b - 2^n)
        S=(a+b)mod2n=a+b2nS = (a + b) \mod 2^n = a + b - 2^n
        • 映射到负数: B(a+b2n)=a+b2nB(a + b - 2^n) = a + b - 2^n
      • 如果a+b<2n1a + b < -2^{n-1}(负溢出):

        a+b=2n+(a+b+2n)a + b = -2^n + (a + b + 2^n)
        S=2n+(a+b)=a+b+2nS = 2^n + (a + b) = a + b + 2^n
        • 映射到正数: B(a+b+2n)=a+b+2nB(a + b + 2^n) = a + b + 2^n

减法一致性

  • 减法转为加法:

    • ab=a+(b)a - b = a + (-b)

    • B(b)=2nbB(-b) = 2^n - b

    • 硬件用加法器:

      B(a)+B(b)=a+(2nb)B(a) + B(-b) = a + (2^n - b)
    • 2n2^n 后得到正确结果。

循环性(溢出处理)

  • 补码形成模 2n2^n 的圆环:

    • 最大正数:2n11=0111...11112^{n-1} - 1 = 0111 ... 1111

    • 加 1:

      2n11+1=2n1=2n2n1=B(2n1)2^{n-1} - 1 + 1 = 2^{n-1} = 2^n - 2^{n-1} = B(-2^{n-1})
    • 最小负数:2n1=1000...0000-2^{n-1} = 1000 ... 0000

    • 减 1:

      2n2n11=2n112^n - 2^{n-1} - 1 = 2^{n-1} - 1
  • 溢出时,数值在 [2n1,2n11][-2^{n-1}, 2^{n-1} - 1] 内循环,硬件无需额外处理。

简单说,补码就像把负数“折叠”到大正数(通过 2nx2^n - x),但设计得非常巧妙,让二进制加法器的结果和数学运算完全吻合。