四种有符号数编码方式

四种有符号数编码方式

1. 原码 (Sign-Magnitude)

核心思想:最高位表示符号(0正1负),其余位表示绝对值。

  • 正数:符号位0,数值位为真值的二进制绝对值
  • 负数:符号位1,数值位为真值的二进制绝对值

例子(8位表示):

  • +18 → 原码:0001 0010
  • -18 → 原码:1001 0010

特点

  • 直观易懂,符合人类习惯
  • 存在+0和-00000 00001000 0000都表示0
  • 加减运算复杂:需要判断符号位,硬件实现麻烦

2. 反码 (Ones' Complement)

核心思想:正数的反码等于原码,负数的反码是原码的符号位不变,其余位按位取反。

  • 正数:与原码相同
  • 负数:符号位保持1,数值位全部取反

例子(8位表示):

  • +18 → 原码:0001 0010 → 反码:0001 0010
  • -18 → 原码:1001 0010 → 反码:1110 1101

特点

  • 存在+0和-00000 00001111 1111都表示0
  • 加减法稍微简化,但仍有循环进位问题
  • 补码出现前的过渡方案,现已基本不用

3. 补码 (Two's Complement) ✅ 最重要!现代计算机标准

核心思想:正数的补码等于原码,负数的补码等于反码加1。

  • 正数:与原码相同
  • 负数:符号位保持1,数值位取反后加1

例子(8位表示):

  • +18 → 原码:0001 0010 → 补码:0001 0010

  • -18

    复制代码
    原码:1001 0010
    取反:1110 1101  (反码)
    加1:1110 1110   (补码)

特点

  • 只有一个00000 0000
  • 范围不对称 :n位补码范围是 -2ⁿ⁻¹+(2ⁿ⁻¹ - 1)
    • 8位:-128 到 +127
  • 加减运算统一:减法可转换为加法,硬件实现简单
  • 现代计算机几乎全部使用补码

快速求负法:从右向左找到第一个1,这个1及其右边的位保持不变,左边的位全部取反。

  • -18的补码 1110 1110 → 从右第一个1在倒数第二位,保留10,左边取反得1110 11,即1110 1110

4. 移码 (Biased Representation / Excess-K)

核心思想:真值加上一个固定偏移量K(通常K=2ⁿ⁻¹),使其全部变为非负数。

  • 公式:移码 = 真值 + 2ⁿ⁻¹
  • 等价关系:移码 = 补码的符号位取反

例子(8位,偏移量K=128):

  • +18 → 补码:0001 0010 → 移码:1001 0010 (符号位取反)
  • -18 → 补码:1110 1110 → 移码:0110 1110 (符号位取反)
  • 0 → 补码:0000 0000 → 移码:1000 0000 (=128)

特点

  • 所有值都是非负的,便于比较大小
  • 主要用于浮点数的阶码(指数部分)
  • 比较两个移码数的大小,就是比较它们对应的真值的大小

综合对比(以4位二进制为例)

真值 原码 反码 补码 移码(K=8)
+7 0111 0111 0111 1111
+6 0110 0110 0110 1110
+5 0101 0101 0101 1101
+4 0100 0100 0100 1100
+3 0011 0011 0011 1011
+2 0010 0010 0010 1010
+1 0001 0001 0001 1001
+0 0000 0000 0000 1000
-0 1000 1111 - -
-1 1001 1110 1111 0111
-2 1010 1101 1110 0110
-3 1011 1100 1101 0101
-4 1100 1011 1100 0100
-5 1101 1010 1011 0011
-6 1110 1001 1010 0010
-7 1111 1000 1001 0001
-8 - - 1000 0000

关键区别总结

特性 原码 反码 补码 移码
0的表示 两种(+0/-0) 两种(+0/-0) 一种 一种(非零值)
表示范围(4位) -7 ~ +7 -7 ~ +7 -8 ~ +7 -8 ~ +7(但编码全是正数)
加减运算 复杂,需判断符号 较简单,但有循环进位 最简单,统一为加法 用于比较,不做加减
硬件实现 复杂 较简单 最简单 简单
主要用途 早期计算机/浮点数尾数 历史过渡 现代整数运算标准 浮点数阶码
符号处理 最高位=符号 最高位=符号 最高位=符号 无符号(全是正数编码)
数值连续性 不连续(有±0) 不连续(有±0) 连续 连续

为什么补码成为标准?

  1. 运算统一性A - B = A + (-B),减法器不需要了
  2. 硬件简化:只需要加法器和补码转换电路
  3. 唯一零表示:避免歧义和硬件复杂度
  4. 表示范围更合理:比原码/反码多表示一个数(-2ⁿ⁻¹)

实际应用场景

  • CPU中的整数:全部使用补码表示和运算
  • 浮点数(IEEE 754)
    • 尾数部分:用原码表示(有符号绝对值)
    • 阶码部分:用移码表示(便于比较指数大小)

快速记忆技巧

  • 原码:最直观,看符号位就知道正负
  • 反码:"反"着来,负数就是取反
  • 补码:负数=反码+1,现代计算机的王者
  • 移码:给真值加个偏移量,全变正数,浮点数用它

这四种编码方式共同构成了计算机处理有符号数的理论基础,其中补码无疑是最重要、最核心的概念。

5.原码和以及反码,补码,移码能表示的整数数和小数范围

编码方式 整数范围 小数范围(定点) 零的表示
原码 -(2ⁿ⁻¹ - 1) ~ +(2ⁿ⁻¹ - 1) 例(8位): -127 ~ +127 -(1-2⁻⁽ⁿ⁻¹⁾) ~ +(1-2⁻⁽ⁿ⁻¹⁾) 例(8位): -0.992 ~ +0.992 +0 和 -0 两个零
反码 -(2ⁿ⁻¹ - 1) ~ +(2ⁿ⁻¹ - 1) 例(8位): -127 ~ +127 -(1-2⁻⁽ⁿ⁻¹⁾) ~ +(1-2⁻⁽ⁿ⁻¹⁾) 例(8位): -0.992 ~ +0.992 +0 和 -0 两个零
补码 -2ⁿ⁻¹ ~ +(2ⁿ⁻¹ - 1) 例(8位): -128 ~ +127 -1.0 ~ +(1-2⁻⁽ⁿ⁻¹⁾) 例(8位): -1.0 ~ +0.992 唯一零
移码 真值: -2ⁿ⁻¹ ~ +(2ⁿ⁻¹ - 1) 编码: 0 ~ (2ⁿ - 1) 例(8位): 真值-128+127<br>编码0255 不用于小数表示 (主要用于浮点数阶码) 唯一零 (编码为2ⁿ⁻¹)

5.1为什么原码和反码范围相同?

5.1.1. 原码定义

原码 = 符号位 + 绝对值的二进制

  • 符号位:0正1负
  • 数值位:n-1位表示绝对值

最大正数0 111...111 = +(2^{n-1}-1)
最大负数1 111...111 = -(2^{n-1}-1)

5.2. 反码定义

反码 = 符号位 + 绝对值的按位取反(负数时)

  • 正数:与原码相同
  • 负数:绝对值按位取反

以4位为例

复制代码
十进制  原码   反码
+3     0011   0011  ← 正数相同
-3     1011   1100  ← 负数取反

关键 :反码的负数表示范围与原码完全一致:

  • 最小的负数模式:1 000...000 在原码中是 -0,在反码中也是 -0
  • 最大的负数模式:1 111...111 在原码中是 -(2^{n-1}-1),在反码中也是 -(2^{n-1}-1)

因为原码和反码都是1位符号号+其它数值位

5.2 为什么补码比原码/反码多一个负数?

根本原因:补码重新定义了 100...000 的含义
二进制模式 原码含义 反码含义 补码含义
100...000 -0(无效/视为0) -0(无效/视为0) -2^{n-1}(有效负数)
补码的巧妙设计

补码中,-0的编码被重新利用来表示多一个负数:

4位时的对比

十进制 原码 反码 补码
-8 无法表示 无法表示 1000
-7 1111 1000 1001
-6 1110 1001 1010
-5 1101 1010 1011
-4 1100 1011 1100
-3 1011 1100 1101
-2 1010 1101 1110
-1 1001 1110 1111
-0 1000 1111
+0 0000 0000 0000

补码"偷"了-0的编码1000来表示-8,所以负数范围多一个。

5.3 移码范围

5.3.1 补码 vs 移码(以4位为例)
二进制编码 补码真值 移码真值 移码编码值
0000 0 -8 0
0001 1 -7 1
0010 2 -6 2
0011 3 -5 3
0100 4 -4 4
0101 5 -3 5
0110 6 -2 6
0111 7 -1 7
1000 -8 0 8
1001 -7 1 9
1010 -6 2 10
1011 -5 3 11
1100 -4 4 12
1101 -3 5 13
1110 -2 6 14
1111 -1 7 15
5.3.2 关键区别解析
1. 编码范围不同
  • 补码编码 :1000(-8) ~ 0111(7)
    从-8到7,共16个数
  • 移码编码 :0000(0) ~ 1111(15)
    从0到15,共16个数
2. 真值范围相同
  • 两种编码都表示 -8到7 这16个整数
  • 只是同一个真值的编码不同
5.3.3 移码的定义与计算
1. 移码公式

对于n位二进制:

\\text{移码} = \\text{真值} + 2\^{n-1}

\\text{移码} = \\text{补码} \\oplus 100...0 \\ (\\text{符号位取反})

2. 举例计算
复制代码
真值 = -5
n=4,偏移量 = 2³ = 8
移码 = -5 + 8 = 3 = 0011

验证:
-5的补码 = 1011
符号位取反:1011 → 0011 ✓
5.3.3 为什么要有移码?
移码的主要优点:
  1. 简化比较运算

    • 移码的真值越大,编码值也越大
    • 可以直接用无符号比较器比较有符号数
  2. 浮点数阶码使用

    • IEEE 754标准中,阶码用移码表示
    • 便于处理正负指数
  3. 直观性

    • 全0编码表示最小真值(-8)
    • 全1编码表示最大真值(7)
对比示例:

比较两个数的大小:

  • 补码比较 :-5(1011) vs 3(0011)
    1011 > 0011(无符号),但-5 < 3(实际)
  • 移码比较 :-5(0011) vs 3(1011)
    0011 < 1011(无符号),且-5 < 3(实际一致)
相关推荐
GGBondlctrl6 个月前
【Redis】Redis核心探秘:数据类型的编码实现与高速访问之道
数据结构·数据库·redis·缓存·编码方式·redis工作过程·单线程模型
风吹草8 个月前
java程序乱码问题
java·编码方式