欢迎光临
我们一直在努力

如何计算一个数的补码(含详细例子)

补码(Two's Complement)是计算机中表示有符号整数最常用的方法。理解补码是学习计算机底层、数字电路、芯片设计的基础。


一、为什么需要补码?

计算机中数据用二进制表示,但二进制本身没有"正负"的概念。为了表示负数,历史上有过三种方案:

表示法优点缺点
原码 直观(最高位表示符号) 有 +0 和 -0 两个零;加减法需要额外判断
反码 加减法稍简化 仍有 +0 和 -0;加减法仍需特殊处理
补码 +0 和 -0 统一;加减法可以用同一套加法器电路实现 略不直观

核心好处: CPU 只需要一个加法器,就能完成加法和减法,硬件电路大大简化。


二、补码的计算规则

对于正数和零

正数的补码 = 原码本身(最高位是符号位 0)

对于负数

负数的补码 = 反码 + 1 = 原码取反(含符号位除外)后 + 1

具体三步法:

  • 写出该数绝对值的二进制原码
  • 按位取反(0 变 1,1 变 0),得到反码
  • 末位加 1,得到补码
  • 或者一个更快的口诀:从右往左数,遇到第一个 1 之前的所有位保持不变,第一个 1 也不变,之后的位全部取反。


    三、详细例子(8 位补码为例)

    8 位补码能表示的范围:-128 ~ +127

    例 1:+5 的 8 位补码

    正数补码 = 原码:

    +5 的原码: 0000 0101
    +5 的补码: 0000 0101 ← 直接就是


    例 2:-5 的 8 位补码(重点)

    方法一:三步法

    步骤 1: 写出 |-5| = 5 的原码: 0000 0101
    步骤 2: 按位取反(反码): 1111 1010
    步骤 3: 末位加 1(补码): 1111 1011

    所以 -5 的 8 位补码 = 1111 1011

    方法二:口诀法(从右往左找第一个 1)

    原码: 0000 0101
    ↑ 从右往左,第一个 1 在最低位
    保持这个 1 和它右边不变(这里它就是最低位,没有右边)
    左边所有位取反
    补码: 1111 1011


    例 3:-1 的 8 位补码

    Apply

    步骤 1: |−1| = 1 的原码: 0000 0001
    步骤 2: 按位取反: 1111 1110
    步骤 3: 末位 + 1: 1111 1111

    所以 -1 的 8 位补码 = 1111 1111(全是 1,很好记)


    例 4:-128 的 8 位补码(边界情况)

    步骤 1: |−128| = 128 的原码: 1000 0000(恰好 8 位)
    步骤 2: 按位取反: 0111 1111
    步骤 3: 末位 + 1: 1000 0000

    所以 -128 的 8 位补码 = 1000 0000

    注意: 8 位补码能表示 -128(最小负数)但不能表示 +128,所以补码的表示范围是不对称的:[-128, +127]。


    例 5:-20 的 8 位补码

    步骤 1: |−20| = 20 的原码: 0001 0100
    步骤 2: 按位取反: 1110 1011
    步骤 3: 末位 + 1: 1110 1100

    所以 -20 的 8 位补码 = 1110 1100

    用口诀法验证:

    原码 20: 0001 0100
    ↑ 从右往左第一个 1(位 2)
    保持它和右边不变 → 100
    左边所有位取反 → 1110 1
    补码: 1110 1100 ✓


    四、补码的"反向解读":如何从补码读出十进制

    规则:

    • 如果最高位是 0:正数,按普通二进制读
    • 如果最高位是 1:负数,对补码再做一次"取反 + 1",得到的就是它的绝对值

    例 6:补码 1111 1011 是多少?

    最高位是 1,是负数
    取反: 0000 0100
    +1: 0000 0101
    对应十进制: 5
    所以原数是: -5 ✓(验证了例 2)

    例 7:补码 1000 0001 是多少?

    最高位是 1,是负数
    取反: 0111 1110
    +1: 0111 1111 = 127
    所以原数是: -127


    五、补码的精髓:用加法做减法

    这是补码最神奇的地方。下面用例子展示。

    例 8:计算 7 – 5(即 7 + (-5))

    把减法转换为补码加法:

    7 的补码: 0000 0111
    -5 的补码: 1111 1011
    ─────────────
    相加: 1 0000 0010

    第 9 位的进位被丢弃(8 位寄存器溢出)

    最终结果: 0000 0010 = +2 ✓

    完美! 用加法器实现了减法,硬件无需专门的减法器电路。


    例 9:计算 -3 + (-5)

    -3 的补码: 1111 1101
    -5 的补码: 1111 1011
    ─────────────
    相加: 1 1111 1000

    第 9 位进位丢弃

    最终结果: 1111 1000

    验证: 最高位是 1,是负数
    取反: 0000 0111
    +1: 0000 1000 = 8
    原数: -8 ✓


    六、不同位宽的补码

    补码的位宽决定了表示范围:

    位宽表示范围-1 的补码最小负数的补码
    4 位 -8 ~ +7 1111 1000 (-8)
    8 位 -128 ~ +127 1111 1111 1000 0000 (-128)
    16 位 -32768 ~ +32767 0xFFFF 0x8000 (-32768)
    32 位 -2³¹ ~ +2³¹-1 0xFFFF_FFFF 0x8000_0000
    64 位 -2⁶³ ~ +2⁶³-1 0xFFFF_FFFF_FFFF_FFFF 0x8000_0000_0000_0000

    例 10:-5 的 16 位补码

    步骤 1: |−5| = 5 的 16 位原码: 0000 0000 0000 0101
    步骤 2: 按位取反: 1111 1111 1111 1010
    步骤 3: 末位 + 1: 1111 1111 1111 1011

    简写: 0xFFFB


    七、补码的几个重要性质

    性质说明例子
    +0 和 -0 唯一 0 的补码只有一个 0000 0000 取反 1111 1111 +1 → 1 0000 0000,丢弃进位 → 0000 0000
    最小负数没有正对应 8 位中 -128 存在,但 +128 不能表示 范围 [-128, +127] 不对称
    符号位扩展 高位补符号位本身(正数补 0,负数补 1)值不变 8 位 1111 1011 (-5) → 16 位 1111 1111 1111 1011 (-5)
    取反 + 1 是自反操作 对补码再做"取反 + 1"得到相反数 -5 补码取反+1 → +5

    例 11:符号位扩展(重要!)

    把 8 位的 -5 扩展为 16 位:

    8 位 -5 补码: 1111 1011
    ↑ 符号位是 1,高位全补 1

    16 位 -5 补码: 1111 1111 1111 1011
    └────────┘ 新增的 8 位全是 1

    而把 8 位的 +5 扩展为 16 位:

    8 位 +5 补码: 0000 0101
    ↑ 符号位是 0,高位全补 0

    16 位 +5 补码: 0000 0000 0000 0101

    这就是 CPU/Verilog 中的"有符号扩展"(sign extension),在指令集设计中极其常见。


    八、Verilog 中的补码运算示例

    module twos_comp_demo;
    reg signed [7:0] a, b;
    reg signed [7:0] result;

    initial begin
    a = 8'd7; // +7 的补码: 0000_0111
    b = -8'd5; // -5 的补码: 1111_1011(编译器自动转)

    result = a + b; // 7 + (-5) = 2

    $display("a = %0d (binary: %b)", a, a);
    $display("b = %0d (binary: %b)", b, b);
    $display("a + b = %0d (binary: %b)", result, result);
    end
    endmodule

    输出:

    a = 7 (binary: 00000111)
    b = -5 (binary: 11111011)
    a + b = 2 (binary: 00000010)


    九、综合速查表(8 位补码)

    十进制二进制补码十六进制
    +127 0111 1111 0x7F
    +64 0100 0000 0x40
    +1 0000 0001 0x01
    0 0000 0000 0x00
    -1 1111 1111 0xFF
    -2 1111 1110 0xFE
    -64 1100 0000 0xC0
    -127 1000 0001 0x81
    -128 1000 0000 0x80

    十、一句话总结

    正数的补码 = 它自己;负数的补码 = 绝对值取反 + 1。补码让计算机用一套加法器实现加减法,是现代计算机和芯片设计的基石。

    需要的话,我可以进一步讲解:

    • 浮点数的表示(IEEE 754)
    • 补码乘法(Booth 算法)
    • 在 Verilog 中实现有符号运算的注意事项
    • 溢出检测(overflow / carry 区别)
    赞(0)
    未经允许不得转载:171主机测评 » 如何计算一个数的补码(含详细例子)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址