数的表示与运算

从位宽、编码和类型规则出发,讲解机器数、整数运算、标志位、浮点精度与运算器题。

数的表示与运算研究两件事:有限位数怎样表示数值,以及运算电路怎样处理这些位。综合题常把它们放进一小段 C 代码中,让你同时回答“位模式是什么”“数值是多少”“结果是否正确”。这三个问题需要分别判断。

这个板块包含哪些知识

按数制与数据表示图谱,可以分成三层:

  • 表示:进制转换、无符号整数、补码范围、IEEE 754 的符号位、阶码和尾数。
  • 运算:加减、移位、乘除的电路实现,以及 CF、OF、ZF、SF 的含义。
  • 转换:整数提升、不同宽度的扩展与截断、有符号和无符号混合运算、整数与浮点数转换、舍入。

先确定位宽和类型,再讨论运算。以 FFH 为例,按 8 位无符号数解释是 255,按 8 位补码解释是 −1;扩展成 16 位时,零扩展得到 00FFH,符号扩展得到 FFFFH。同一个低 8 位,后续结果可以不同。

整数题重点看表示范围和结果位;浮点题还要区分范围够不够与精度够不够。

常见考点与题型

综合题可能组合下面几类小问。先看要求求什么,再确定需要调用哪些知识。

题型题干中的线索解题思路
机器数与真值互换给十六进制、类型或字长补足位宽,按指定编码解读;负补码可用无符号值减 2ⁿ
C 表达式与类型转换赋值、混合比较、循环条件先按题设类型规则确定运算类型,再算位模式,最后解释赋值结果
整数运算与标志位加减、乘积截断、条件转移先算数学结果,再对照范围与电路标志;CF 与 OF 分开判断
浮点编码与精度IEEE 754、精确表示、舍入、溢出规格化后填字段;分别核对有效位数和指数范围
运算器实现与性能串行、并行乘除、周期数按题给电路和迭代次数算时间,说明速度与硬件开销的取舍

解题前要弄清的关系

一、位串没有意义,解释方式才有

  1. 同一个位串可以被解释成三种东西:无符号数、补码、IEEE754 浮点数,见 整数的表示 和 IEEE 浮点数表示
  2. n 位补码范围 ,n 位无符号范围
  3. 整数转换常涉及两类操作:改解释(同长度 signed ↔ unsigned,位串一个不动)或改长度(变长时零扩展 / 符号扩展,变短时直接截断),见 有符号整数和无符号整数、不同长度的类型转换
  4. 混合整数运算先看整数提升、类型等级与表示范围;同等级的 int 与 unsigned int 运算通常转为 unsigned int,比较也按无符号数进行——2017#43 第 1 问的死循环就是这一条

二、运算电路和标志位

  1. 加减共用一个加法器:减法先把减数各位取反、末位加 1,再当成加法送进去。所以无符号加减和带符号加减走的是同一套电路,区别只在事后怎么读这串结果位,见 加法运算电路、减法运算电路
  2. 四个标志位就是这次加法顺手引出来的四根线,每根只回答一个问题:结果是否为 0(ZF)、结果最高位是什么(SF)、最高位向外有没有进位或借位(CF)、最高两位的进位是否不相等(OF)。四个同时产生,但 CF 只在把结果读成无符号数时有意义,OF 只在读成带符号数时有意义,见 条件标志
  3. 乘法是「加一次、右移一位」重复 n 遍,所以 n 位乘 n 位的完整结果有 2n 位;把这 n 遍摊开成一片电路就是阵列乘法器——快,但面积大。真题只问两件事:哪种实现更快,以及只保留低 n 位会不会丢掉信息。见 乘法运算电路
  4. 除法是「减一次、左移一位」重复 n 遍,因此有两种失败方式:除数为 0,以及商放不进目标寄存器(商溢出)。这是两个不同的异常,不能合成一句,见 除法运算电路
  5. 乘除 2ᵏ 可以直接用移位代替(左移 k 位、算术右移 k 位),但负数算术右移是向下取整,和 C 语言除法的向零取整不一致——被问「能不能用移位实现」时这一句必须交代

三、IEEE754 单精度先把 32 位切成 1 + 8 + 23,其余全是这一刀的推论

  1. 切法与偏置:符号 1 位 ‖ 阶码 8 位 ‖ 尾数 23 位,阶码里存的是「真实指数 + 127」,规格化数的尾数前面还隐含一个 1,见 IEEE 浮点数表示
  2. 尾数那一刀给出有效位 24 位(隐含的 1 加 23 位尾数),在规格化数的指数范围内,需要超过 24 个有效二进制位的数不能精确表示;非规格化数的有效精度还会下降
  3. 阶码那一刀给出「溢出在哪」:8 位阶码里可用的只有 1~254(真实指数 −126~127),全 0 与全 1 留作特殊值——全 1 且尾数全 0 是 ±∞(+∞ 的机器数就是 7F800000H),全 1 且尾数非 0 是 NaN,见 异常值
  4. 所以判浮点溢出应看规格化和舍入之后的阶码有没有越界;尾数在运算中溢出只会导致尾数右移、阶码加 1,它本身不是溢出,见 溢出判断
  5. 浮点加减固定五步:对阶(小阶的尾数右移,向大阶靠)→ 尾数加减 → 规格化 → 舍入 → 判阶码溢出,见 浮点数加减

各类题的解法

整数代码题可以按下面的顺序分析;浮点编码与精度题则使用后面的独立流程。位宽、类型和题设机器模型是两类题共同的前提。

第一步:先写位数和范围

在草稿最上面注明三项:字长几位、每个变量是什么类型、这些类型的取值范围。2011#43 是 8 位机,unsigned 范围 0~255、int 范围 −128~127,题里的 134 和 246 都超出了 int 范围——这一行写下来,后面四个小问全部有了依据。

第二步:每条 C 语句翻成两行

位串:  运算按位算出来的结果(十六进制,位数补齐)
解释:  这个位串按该变量的类型读出来是多少

在题设采用同宽补码转换模型时,可先求位模式,再分别解释有符号与无符号值。宽度变化或整数与浮点互转时,需要另外计算转换结果;x - y 这种无符号减法照样按补码加法算,只是溢出判据换成 CF。

第三步:溢出判断按类型对号入座

运算判据
无符号加最高位向外有进位(CF = 1)
无符号减有借位,即被减数小于减数
带符号加减最高两位进位不相等(OF = Cn ⊕ Cn−1),加法也可用“两正得负、两负得正”,减法应按减法符号关系判断
乘法只取低 n 位无符号:高 n 位不全为 0;带符号:高 n 位不是低 n 位的符号扩展
浮点只看规格化舍入后的阶码是否越界,尾数溢出不算

2020#43 第 4 问就是倒数第二行:n = 32、x = 2³¹−1、y = 2 时,umul 不溢出而 imul 溢出。

第四步:机器数写成补齐的十六进制

8 位写两个十六进制位,32 位写八个,末尾统一带 H。2017#43 要求同时给出 f1(23) 的 00FFFFFFH 和 f2(23) 的 4B7FFFFFH——同一个数值的两种编码要分别写清阶码怎么来的、尾数怎么来的。

浮点题:把精度上限与范围上限分开求

以 2017#43 给定的函数为例,先从表达式推导所需有效位数与指数,再分别与类型限制比较。下面的 n 值只对应这道题,不能作为通用阈值:

  • f1(n) 与 f(n) 相等的最大 n 是 30(int 最大值是 2³¹−1);
  • f2(n) 结果精确的最大 n 是 23(f(23) 恰好 24 个 1,不需舍入);
  • f2(n) 不溢出的最大 n 是 126(再大一档舍入后阶码就到 255)。

浮点编码:先规格化,再填写字段

以单精度表示 5.5 为例:5.5=101.1₂=1.011₂×2²,符号为 0,阶码为 2+127=129,尾数字段填 011 后补 0,得到 40B00000H。反向解码时先检查阶码是否为全 0 或全 1,不能把特殊编码也按隐含 1 的规格化公式计算。

判断精确性,要看数值的二进制表示实际需要多少有效位。2²⁴ 能被单精度精确表示,但 2²⁴+1 需要 25 个有效位,无法精确表示;这说明“整数很大”本身不是不精确的充分理由。指数超出范围与尾数需要舍入,也要分别作答。

运算器与条件转移:从电路结果回到比较语义

加减题先注明是无符号还是补码解释,再选择 CF 或 OF;若题目问分支是否发生,还要按指令定义组合 ZF、SF 等标志。不能只看结果最高位就判断所有大小关系。

乘除实现题按题给数据通路列出一次迭代做什么、重复多少次、每次几个周期,再乘时钟周期。比较实现时,分别说明延迟与硬件规模;“并行更快”不能替代题目要求的具体时间计算。

历年题索引

真题主线这一年特别问了什么
2011#438 位机的无符号与补码加减四种加减能否共用一个加法器、哪条语句溢出
2013#44条件转移 + 标志寄存器无符号数「≤」转移要用哪几个标志位
2017#43int 与 float 计算同一个 f(n)死循环原因、机器数、精确与溢出的最大 n
2020#43乘法的三种实现执行时间长短比较、取低 n 位的溢出判断
2022#43数据通路 + 标志位写出 SF 与 OF 的逻辑表达式
2024#43控制信号 + ALU 标志slli 与 lw 的 Ext 和 ALUctr 取值
2025#44补码除法器数据通路除法异常的两种情形与异常响应中 CPU 的动作

易错清单

  • 把整数与浮点转换当成位模式重解释。相同宽度不代表编码相同;整数与浮点互转需要重新编码,还可能舍入或越界。
  • 未确定公共类型就比较。应先按题设类型宽度处理整数提升和通常算术转换,不能把“出现 unsigned”直接当成结论。
  • 用 CF 判带符号溢出。CF 和 OF 是两套判据,2013#44 专门考这个边界。
  • 浮点数以为 32 位就能精确表示 32 位整数。有效位只有 24 位。
  • 尾数溢出就下结论「结果溢出」。要等规格化和舍入之后再看阶码。
  • 机器数少写位数。8 位就补足两位十六进制,不能只写有效数字。

上一页:数据结构大题;下一页:存储系统。