计算机-原码反码补码,为什么用补码?

一、什么是原码反码补码

在计算机系统中,数值的存储和运算依赖于原码、反码、补码三种二进制表示方法。它们的核心目标是解决符号位参与运算的问题,尤其是负数的加减法。

1.原码(Sign-Magnitude)

直观易读,但是加减法复杂,存在双零

  • 定义:原码是最直接的二进制表示方法。最高位为符号位,0 表示正数,1 表示负数,其余位表示数值的大小。
  • 示例:以 8 位二进制数为例,正数 5 的原码是 00000101,负数 - 5 的原码是 10000101。
  • 特点:简单直观,与真值转换方便。但存在两个问题,一是有 +0 和 -0 之分,+0 的原码是 00000000,-0 的原码是 10000000;二是用原码进行加减法运算时,对于同号数相减或异号数相加,不能直接进行运算,否则会出现错误结果。

2.反码(Ones' Complement)

改进原码加减问题,但仍需处理进位,存在双零

  • 定义:正数的反码与原码相同,负数的反码是对原码除符号位外的各位取反。
  • 示例:正数 5 的反码是 00000101,负数 - 5 的反码是 11111010。 +0 的反码是 00000000,-0 的反码是 11111111。
  • 特点:作为原码到补码的过渡,可用于求补码。但反码也存在 +0 和 -0 两种表示,且在进行加减法运算时,虽然解决了原码运算的部分问题,但仍不够方便,也会出现错误结果。
    • 循环进位:加减法需处理最高位的进位(若进位存在,需加回最低位)。

      • 例如:5 + (-3) 转换为 0000 0101 + 1111 1100 = 1 0000 0001,需加 1 得到 0000 0010(即 2)。

3.补码(Two's Complement)

统一加减法,无双零,效率最高,但负数转换需额外步骤。通过补码,计算机能够高效、准确地处理负数运算,成为现代数字系统的基础编码方式。

  • 定义:正数的补码与原码相同,负数的补码是对原码除符号位外的各位取反后加 1。
  • 示例:正数 5 的补码是 00000101,负数 - 5 的补码是 11111011。
  • 特点:补码是现代计算机中表示有符号整数的标准方法。它消除了原码和反码中 “零” 的两种表示,0 只有一种表示形式,即 00000000。而且在补码系统中,加法和减法可以使用相同的电路实现,简化了硬件设计,大大提高了计算机运算的效率和准确性。
    • 统一加减法:所有运算均可通过加法完成(无需减法器),无需处理符号位。实用性高,硬件设计简单。补码运算溢出时直接截断高位(如 127 + 1 = -128)。

    • 消除双零:仅 0000 0000 表示零。

    • 扩展表示范围n 位补码可表示 [-2^{n-1}, 2^{n-1}-1],例如 8 位范围为 -128 到 +1271000...000 表示最小负数(如 8 位的 -128)。

二、三者关系与转换

反码是解决原码减法运算错误问题的,因为原码直接参与加减法运算时,符号位也会参与计算,导致逻辑错误,补码在反码之后发展出来的,其设计目的是为了解决反码存在的缺陷并进一步优化计算机运算规则。

  • 转换规则

 1. 原码 → 反码

  • 正数:原码 = 反码
    示例:+7 的原码 / 反码 = 0000 0111
  • 负数:符号位保留,数值位逐位取反
    示例:-7 的原码 = 1000 0111 → 反码 = 1111 1000

2. 原码 → 补码

  • 正数:原码 = 补码
    示例:+7 的补码 = 0000 0111
  • 负数:反码 + 1
    示例:-7 的原码 = 1000 0111 → 反码 = 1111 1000 → 补码 = 1111 1001

3. 补码 → 原码

  • 正数:补码 = 原码
    示例:+7 的补码 = 0000 0111
  • 负数:补码 - 1 → 取反(符号位保留)
    示例:-7 的补码 = 1111 1001 → 减 1 得1111 1000 → 取反得原码1000 0111

  •  三者关系

1. 正数的原码、反码、补码相同。

2. 负数的反码是原码数值位取反,补码是反码加1。

3. 补码是反码的扩展,通过加1操作解决了反码运算中的溢出问题(如1-1不会得到-0)。

三、反码,补码如何统一正负数?

我们用 B2D_{w} 表示 “二进制补码转十进制(Binary to Decimal)” 的计算过程,其中 w 为二进制数的位长。计算时,将二进制每一位的值x与对应权重 2^i(i 从 0 开始,自右向左递增表示位数)相乘后累加。对向量x有:

实际上它们的值就是"除符号位部分"相对于符号位权重值(-2^{w-1})的偏移量。可以用统一的方式解释正负数,最高位为0表示正数,为1则为负。反码在则是相对于(-2^{w-1}+1)的偏移量,但是原码就不行了,它的符号位就只是符号位!而这个偏移量的绝对值在补码中还有另外一个身份“模“(除符号位数值部分)。

四、补码统一加减法的数学原理

1. 核心原理:模运算(Modular Arithmetic)

计算机中固定位数的二进制运算本质是模运算。对于 n 位二进制数,模为2^{^{n}},所有运算结果自动对模取余(即溢出高位被舍弃,保留余数)。

示例:4 位二进制数的模为 2^{^{4}}=16,计算 17 mod 16 = 1。

2. 补码定义

负数-A 的补码定义为:[-A]_{bu} \equiv 2^{^{n}} - A    (mod 2^{^{n}}), 在模2^{^{n}} 下,与-A等价的正数

示例:4 位二进制中,-2 的补码为 16 - 2 = 14,即二进制 1110

3. 减法转换为加法

减法可通过补码转换为加法:a - b \equiv a + (-b)_{bu}  (mod 2^{^{n}})

示例分析:计算 3 - 2

步骤 1:数值转换为补码

  • 3 的补码:正数补码与原码相同,即 0011
  • -2 的补码:16 - 2 = 14,即 1110

步骤 2:二进制加法

将补码直接相加:

  0011  (3)
+ 1110  (-2的补码,即14)
--------
 10001  (结果为17)

步骤 3:溢出处理

4 位二进制仅保留低 4 位,最高位的 1 被舍弃,得到 0001数学意义:结果等价于 17 mod 16 = 1,对应十进制 1

4. 模运算的类比

       模运算的一个实际场景就是表盘,可以用它来辅助理解模运算。补码实际是把以0开头的一半数(n-1位)表示正数,把 以1开头的一半数表示负数。加上一个正数就不必说了,减去一个正数就等于加上一个负数,或加上这个数的补数(对于模运算来说)。
 

就拿这个表盘来说,它现在指向2点钟方向, 如何拔回12点钟方向?两种方式:

  • 一种是顺时针加10, 转过大半圈自然回到12点,而且是顺着来的(加)。
  • 一种是逆时针减2,这个就是直接减,方向是逆着的(减)。

这就是模(当前表盘模为12)的场景,同理可以拔回1点/2点/3点方向,都是一样的。 上面的说法是已和起点和终点,,求转动的点数。 现在换一种说法,若已知起点(s)和逆时针方向(减法)转运的点数(m),设终点为x,则必有反向的转动点数(模-m)使之从起点(s)到达终点(x)。在这个过程中指针会穿过12点(模),即为溢出, 这里12其实也是0点,而8位字节就相当于刻度为256的表盘。

五、为什么负数的补码是其对应正数的按位取反再加 1?

正数和0的补码就是该数字本身,负数的补码则是将其对应正数按位取反再加 1。

根据补码特性,字长为 w 的补码和补码的相反数相加,得到的是 2^{^{n}},如 0001 + 1111 = 10000(即 16)。补码和补码按位取反的数相加得到的是[111...1], 即 2^{^{n}} - 1,如 0001 + 1110 = 1111(即 10000 - 1)。用后一个等式减去前者,我们就得到了:

1111(负数的补码) = 1110(正数按位取反)+ 1

如果是负数(-A),求得的补数实际是其绝对值(|-A|)的补数(符号位不变),于是我们有了 “负数的补码(无符号)则是将其对应正数按位取反再加 1” 这个结论。

六、为什么补码的符号位可以直接参与运算?

补码的符号位可以直接参与运算,是因为其设计基于模 2^{^{n}}运算的数学特性,使得符号位与数值位在运算中被统一处理:

1、模运算的统一处理

补码的本质是通过模 2^{^{n}} 运算将负数映射到正数区间。对于 n 位补码:

  • 符号位是最高位(第 n-1 位),0 表示正数,1 表示负数。
  • 符号位的值-2^{n-1}(例如,8 位补码中,符号位为 1 时表示 -128)。

符号位参与运算时,其值会被视为数值的一部分,与其他位共同满足模 2^{^{n}} 的规则。例如:

  • 补码加法 [a]_{bu} + [b]_{bu}的结果自动对2^{^{n}}取模,符号位的进位被自然舍弃。

2、代数证明:符号位参与运算的正确性

符号位参与运算的正确性可以直接整体看(A+B)的补值跟(A补+B补)的结果是否恒等即可,也就是无论 A 和 B 的正负如何,下面等式成立(在n 位补码表示系统中)。

  • 分场景验证

    • 均为正数:补码即自身,相加若未溢出,结果直接为和的补码;若溢出,模2^{^{n}}处理后仍符合补码规则。
    • 一正一负:负数补码通过 2^{^{n}}+负数表示,相加后经模2^{^{n}} 运算,自然得到和的补码。
    • 均为负数:补码相加后,模 2^{^{n}}运算会生成两负数和的正确补码。

符号位的参与不会破坏这一性质:

  1. 正数 + 负数: 例如,计算 3 + (-2)(4 位补码):0011 (3)+1110 (-2)=10001 (mod 16 后为 0001 (1)) 符号位(最高位)的进位被舍弃,结果正确。

  2. 负数 + 负数: 例如,计算 -3 + (-2)(4 位补码):1101 (-3)+1110 (-2)=11011 (mod 16 后为 1011 (-5))符号位的进位同样被舍弃,结果正确。

3、补码的符号位与数值位的统一性

补码的符号位与数值位在数学上是等价的:

  • 符号位的权值为 -2^{n-1} ,但在模 2^{^{n}}下,其权值可以表示为 2^{n-1},而数值位的权值为2^{_{n-2}}, 2^{n-3}, ... 1。
  • 当符号位参与加法时,其权值与数值位的权值共同作用,结果符合模2^{^{n}}的运算规则。

4、总结

补码的符号位直接参与运算的核心原因是:

  • 模运算的数学保证:补码加法天然满足模2^{^{n}}的规则,符号位的进位被自动舍弃。
  • 权值统一:符号位的权值-2^{n-1}与数值位的权值共同构成完整的数值表示。

首先,我们需要了解如何将十进制转换成二进制的原码反码补码。 1. **原码**:正数直接表示,负数则最高位为1(对于有符号整数)。 - **95 (十进制)**: 原码 = 000001010101(因为95在8位内,不足8位补0) - **-131 (十进制)**: 原码 = 111110100011 (负数最高位为1) 2. **反码**:对原码取反,然后加1(对于有符号整数)。负数的反码是除符号位外全变1。 - **95 (十进制)**: 反码 = 111110101010 (+95的反码- **-131 (十进制)**: 反码 = 000001011100 (-131的反码) 3. **补码**:也是对原码取反,然后加1,但对于负数,有一个特殊情况:零的补码等于其本身。 - **95 (十进制)**: 补码 = 111110101010 (+95的补码,无需调整) - **-131 (十进制)**: 补码 = 000001011101 (-131的补码,注意最后一位由1变为0) 4. **浮点数的原码反码补码**: - **0.125 (十进制)**: 由于是小数,通常会采用偏移二进制表示法,即在最高位后面跟上实际值的二进制。0.125 = 1 / 8 = 0.00011001... - 原码 = 000000000000011001000... (保留足够位数) - 反码 = 11111111111110011111100... (先取反再加1) - 补码 = 11111111111110011111100... (小数部分不变,不需要加1) - **-0.875 (十进制)**: 同样是小数,可以将其转化为二进制形式 -0.125 * 8 = -1 = -1000... - 原码 = 100000000000001110000... (带符号,注意最左一位) - 反码 = 01111111111111000111100... (先取反再加1) - 补码 = 01111111111111000111100... (小数部分不变,不需要加1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值