第三章 数据表示与编码:进制转换、原码、反码、补码、移码与定点数表示范围

计算机系统中最底层的语言是二进制,但人类习惯使用十进制。如何在这两种进制之间建立精确、高效的映射,是计算机组成原理的基石。本章将系统讲解进制转换的通用方法,深入剖析原码、反码、补码、移码四种机器数编码的定义、转换规则与适用场景,并重点推导定点数(含纯小数与纯整数)的表示范围。理解这些内容,是后续学习定点运算、浮点数标准(IEEE 754)以及ALU设计的前提。

数据表示与编码核心知识结构 机器数编码体系 原码 符号位 + 值 反码 原码按位取反 补码 反码 + 1(模运算) 移码 补码符号位取反(偏置) 定点数表示范围 纯小数:-(1-2⁻ⁿ) ~ +(1-2⁻ⁿ) | 纯整数:-(2ⁿ) ~ +(2ⁿ-1) 加减法运算(补码) 浮点数阶码(移码) 数据存储与传输 核心:符号数值化 + 模运算 + 统一加法器

3.1 进制转换:从十进制到二进制的通用方法

核心原理:位权展开与基数除法

任何进制数的本质是“位权”的线性组合。十进制数 \(D = \sum_{i=-m}^{n-1} d_i \times 10^i\),二进制数 \(B = \sum_{i=-m}^{n-1} b_i \times 2^i\)。进制转换的核心就是求解二进制各位系数 \(b_i\)。整数部分采用“除2取余,倒序排列”;小数部分采用“乘2取整,正序排列”。

操作流程:整数与小数分离处理

  1. 整数部分:将十进制整数反复除以2,记录每次的余数(0或1),直到商为0,将余数从下往上排列。
  2. 小数部分:将十进制小数反复乘以2,记录每次的整数部分(0或1),直到小数部分为0或达到精度要求,将整数部分从上往下排列。
  3. 合并:整数结果 + 小数点 + 小数结果。
案例拆解:将十进制数 13.625 转换为二进制。
整数部分 13:13÷2=6 余1,6÷2=3 余0,3÷2=1 余1,1÷2=0 余1 → 倒序得 1101。
小数部分 0.625:0.625×2=1.25 取1,0.25×2=0.5 取0,0.5×2=1.0 取1 → 正序得 101。
最终结果:13.625₁₀ = 1101.101₂。

常见误区

  • 小数精度陷阱:十进制小数不一定能精确转换为有限位二进制小数(如0.1₁₀ = 0.000110011...₂循环),需根据精度要求截断。
  • 顺序混淆:整数部分余数要倒序,小数部分整数位要正序,两者方向相反,极易出错。
  • 八进制/十六进制捷径:二进制与八进制(3位一组)、十六进制(4位一组)之间可直接分组转换,无需经过十进制中转。

3.2 四种机器数编码:定义与转换

核心原理:符号数值化与模运算

计算机无法直接存储“+”和“-”符号,必须将符号编码为0(正)和1(负)。原码最直观,但加减法运算复杂;补码通过“模”的概念将减法转化为加法,使得符号位可以参与运算,从而简化硬件设计。移码则是在补码基础上将符号位取反,用于浮点数阶码的比较。

编码类型 正数表示 负数表示 零的表示 主要用途
原码 符号位0 + 值 符号位1 + 值 +0:0000;-0:1000 乘除法、浮点数尾数
反码 同原码 原码按位取反(符号位不变) +0:0000;-0:1111 补码的中间过渡
补码 同原码 反码 + 1 唯一:0000 整数加减法运算
移码 补码符号位取反 补码符号位取反 唯一:1000 浮点数阶码、比较大小

转换规则与速算技巧

  • 原码 → 反码:正数不变;负数符号位保持1,数值位逐位取反。
  • 反码 → 补码:正数不变;负数在反码基础上末位加1。
  • 补码 → 原码:正数不变;负数对补码再次求补(取反加1)即得原码。
  • 补码 → 移码:符号位直接取反,数值位不变。
  • 速算口诀:补码负数 = 从右往左找到第一个1,该位左边所有位取反(符号位不变)。
实战场景:以8位机器数为例,求 -5 的四种编码。
5 的二进制为 0000 0101。
原码:1000 0101(符号位1,数值位101)
反码:1111 1010(符号位不变,数值位取反)
补码:1111 1011(反码+1)
移码:0111 1011(补码符号位取反)
验证:补码 1111 1011 转回十进制,先取反加1得 0000 0101 = 5,加上负号即 -5。

常见误区

  • 补码的“+1”位置:反码加1是对整个反码数值位加1,若产生进位会向符号位传递,但符号位不参与运算。
  • 零的唯一性:原码和反码都有“+0”和“-0”两种表示,而补码和移码的零是唯一的,这是补码能多表示一个最小负数(-2ⁿ⁻¹)的原因。
  • 移码与补码的关系:移码不是独立编码,它只是补码的符号位取反,目的是让所有数值的大小顺序与无符号数一致,便于硬件比较。

3.3 定点数的表示范围

核心原理:定点数的格式约定

定点数约定小数点位置固定不变。常见两种格式:定点纯小数(小数点固定在符号位之后)和定点纯整数(小数点固定在最低位之后)。n位定点数包含1位符号位和(n-1)位数值位。

表示范围推导

格式 编码类型 最小值 最大值 说明
定点纯小数
(n位含符号)
原码/反码 -(1-2⁻⁽ⁿ⁻¹⁾) +(1-2⁻⁽ⁿ⁻¹⁾) 关于原点对称,有±0
补码 -1 +(1-2⁻⁽ⁿ⁻¹⁾) 最小负数可到-1(1000...0)
定点纯整数
(n位含符号)
原码/反码 -(2ⁿ⁻¹-1) +(2ⁿ⁻¹-1) 关于原点对称,有±0
补码 -2ⁿ⁻¹ +(2ⁿ⁻¹-1) 最小负数多一个-2ⁿ⁻¹
关键推导:以8位补码定点整数为例,最大正数为 0111 1111 = 127 = 2⁷-1;最小负数为 1000 0000 = -128 = -2⁷。补码的1000 0000没有对应的原码和反码,它被约定为-128。因此8位补码整数范围是 [-128, 127],而原码/反码范围是 [-127, 127]。

实战场景:溢出判断

在定点数运算中,结果超出表示范围即发生溢出。例如8位补码整数运算:120 + 20 = 140,但140 > 127,结果溢出。硬件上可通过“双符号位”或“最高位进位与符号位进位异或”来判断溢出。

风险提示:溢出与进位是两个不同概念。进位是最高位产生的进位,溢出是结果超出表示范围。例如 1000 0000 + 1000 0000 = 1 0000 0000,有进位但结果 -128 + (-128) = -256 溢出;而 1111 1111 + 0000 0001 = 1 0000 0000,有进位但结果 -1 + 1 = 0 未溢出。判断溢出必须看符号位变化,不能只看进位。

总结复盘

  • 原码:人类最易理解,但运算电路复杂,不适合加减法。
  • 补码:现代计算机整数运算的标准编码,统一了加减法,零唯一。
  • 移码:专为浮点数阶码设计,便于比较大小。
  • 定点数范围:补码比原码/反码多表示一个最小负数,这是模运算带来的“红利”。

掌握这四种编码的转换与定点数范围,是后续学习ALU设计、浮点数IEEE 754标准以及数据校验(如CRC)的基础。建议读者反复练习8位和16位机器数的编码转换,并尝试用程序验证结果。