Appearance
浮点数表示(IEEE 754)
2026 大纲 二(四)1 浮点数的表示:IEEE 754 标准。
32 位怎么分,决定了这一节的全部内容
浮点数的定义只有一行:
但真正决定一切的是这 32 位(或 64 位)怎么分给
🔴 阶码定范围、尾数定精度,两者在同一份预算里抢位置。 这就是浮点数所有权衡的源头:想要更大的范围就得多给阶码几位,代价是尾数变短、精度下降。后面讲的范围、精度、能不能精确表示、怎么舍入,全都从这一句往下推。
分配之外还有两个设计决定,各自解释了一整类现象。第一个是阶码用移码:
🔴 两条理由——① 加偏置后真值的顺序被原样保留,于是(同号时)整个位串按无符号整数比大小就是数值大小,硬件可以直接比;② 移码下的全 0 与全 1 恰好是指数的两个端点,把它们征用来表示特殊值,只切掉数轴的末梢。⚠️ 偏置常数是
(单精度 127、双精度 1023),不是 。
第二个是隐藏位:
🔴 二进制规格化尾数的最高位恒为 1,所以不存它。23 位字段因此能表示 24 位有效数字(双精度 52 → 53)。代价是这个格式表示不出 0——整张特殊值表就是被这个代价逼出来的。
⚠️ 顺带记一条:尾数用原码,符号单独放在
交互可视化
一、字段划分
| 字段 | 单精度 float(32 位) | 双精度 double(64 位) |
|---|---|---|
| 符号 | 1 位, | 1 位, |
| 阶码 | 8 位, | 11 位, |
| 尾数 | 23 位, | 52 位, |
| 偏置常数 bias | ||
| 有效位数 | 24 位(含隐藏位) | 53 位(含隐藏位) |
| 规格化数的指数范围 |
规格化要求尾数写成 1.:
白赚一位精度,欠下的是
二、五类取值
| 阶码 | 尾数 | 含义 | 真值 |
|---|---|---|---|
| 全 0 | 正零、负零,比较时相等 | ||
| 全 0 | 非规格化数 | ||
| 全 1 | 如 | ||
| 全 1 | NaN | 如 | |
| 任意 | 规格化数 |
所以单精度规格化数的真实指数是
这张表有三处最容易记岔:
🔴 阶码全 0 不等于 0,全 1 不等于
。阶码只决定走哪条分支,尾数决定分支内取什么:全 0 且尾数全 0 才是 ,尾数不全 0 是非规格化数;全 1 且尾数全 0 才是 ,不全 0 是 NaN。
🔴 非规格化数的指数是
,单精度是 不是 。 记法:它与最小规格化数共用同一个指数,区别只在隐藏位一个是 0、一个是 1。
🔴 有效位是 24 位不是 23 位,差的那一位是隐藏位。而且只有规格化数才有隐藏位 1,非规格化数的隐藏位是 0——前导零越多有效数字越少,这正是非规格化区精度逐渐退化的原因。
这张表不是五条规则,是从"0 表示不出来"一路推出来的(想弄清为什么征用的是阶码全 0、非规格化数的指数为什么必须取 1-bias 时展开)
先给"阶码定范围、尾数定精度"一点量纲感。 定点数把全部位都用来存有效数字,位权是固定的:想表示
推导链:
- 隐藏位使
,0 表示不出来 必须征用一个位串专门表示 0。 - 征用哪个?移码下只能从数轴末梢下手,于是取阶码全 0。为了让
都有编码,规定阶码全 0 且尾数全 0 时为 ,符号由 决定。 - 阶码全 0 被征用后,尾数不全 0 的那些位串(
个)就闲置了。丢掉可惜——把它们改成"隐藏位为 0"来解释,即 ,正好能表示比最小规格化数还小的一批数,称为非规格化数。 - 数轴一端征用了,另一端(阶码全 1)对称地拿去表示"超出范围"和"没有定义":尾数全 0 表
,尾数不全 0 表 NaN。 - 剩下的阶码
才是规格化数。
非规格化数的指数为什么是
| 值 | |
|---|---|
| 最大非规格化数(指数取 | |
| 最小规格化数 | |
| 两者之差 | |
| 相邻非规格化数之间的间隔 |
后两行完全相等——从非规格化区跨到规格化区,数的疏密没有任何跳变。如果指数取
非规格化数存在的全部意义就是填补 0 到最小规格化数之间的空隙,让下溢变成"渐进"的而不是"一步归零"。指数取
是让这个填补严丝合缝的唯一取值。
三、阶码为什么用移码
阶码要能表示负指数,必须是带符号编码。候选有原码、补码、移码,理由有两条,第二条更决定格式设计。
理由一:比大小可以直接按位串比。 移码是"真值加偏置常数",加完后真值的顺序被原样保留到无符号整数的顺序里。于是阶码在高位、尾数在低位这样一排,一条整数比较指令就够了。补码做不到——补码里
理由二:把"两个极端位串"腾到了数轴两端。 IEEE 754 需要一些位串表示
| 阶码编码 | 全 0 代表的指数 | 全 1 代表的指数 | 挖走它们等于 |
|---|---|---|---|
| 补码 | 在数轴正中间挖两个洞 | ||
| 移码 | 最小指数 | 最大指数 | 只切掉数轴的两个末梢 |
移码下损失的只是最极端的量级——那个量级本来也接近溢出。换成补码,被挖掉的就是最常用的
偏置常数为什么取 2^{k-1}-1 而不是一般移码的 2^{k-1}(想核对正负指数范围为什么不对称时展开)
全 0 和全 1 被征用后,可用阶码只剩
若偏置仍取 128,范围会变成
顺带一提基数:有些早期格式基数取 16(如 IBM 370 短浮点数),规格化尾数的最高一位十六进制数码可以是
四、范围与精度:四个数不要混
| 问的是 | 单精度的答案 | 怎么来的 |
|---|---|---|
| 最小规格化正数 | ||
| 最小正数(含非规格化) | 非规格化最小: | |
| 最大正数 | ||
| 能精确表示的最大整数 | 有效位只有 24 位, |
超过
这张表里的四个数最容易互相串,两组区别要盯死:
🔴 "能表示"与"能精确表示"是两个问题。 最大正数
由阶码决定;能精确表示的最大整数 由尾数决定—— 会被静默地存成 。问法里"精确"这两个字必须逐字读。
🔴 最小正数与最小规格化正数差
倍( 与 ),差的正是整个非规格化区。题面里有没有"规格化"三个字,答案差七个数量级。
由此得到的选型判据:先看范围够不够(
int 与 float 相互转换时具体丢什么,见 C 语言中的数据类型与转换。
五、哪些数能被精确表示
判据只有一条:一个十进制小数能用有限位二进制小数精确表示,当且仅当它化成最简分数后,分母是 2 的幂。
| 数 | 最简分数 | 分母 | 能否精确表示 |
|---|---|---|---|
| 2.0 | ✓ | ||
| 2.5 | ✓ | ||
| 1.25 | ✓ | ||
| 0.4375 | ✓ | ||
| 1.2 | 5 | ✗ | |
| 0.1 | ✗ |
分母里只要含有 2 以外的质因子(5、3……),二进制展开就是无限循环的,只能截断存储。这就是 0.1 + 0.2 != 0.3 的根源。
六、舍入
| 模式 | 规则 | 别名 |
|---|---|---|
| 就近舍入(中间值取偶) | 舍到最近的可表示数;正好在两个可表示数正中间时,取尾数末位为 0(偶数)的那个 | 默认模式 |
| 朝 | 总取数轴上右边那个可表示数 | 正向舍入、朝上舍入 |
| 朝 | 总取数轴上左边那个可表示数 | 负向舍入、朝下舍入 |
| 朝 | 直接截断丢弃多余位,取更靠近原点的那个 | 截断、恒舍法 |
二进制下"是不是正中间"有一条机械判据——只看被丢弃的那串位:
| 被丢弃位串 | 与半个末位比 | 怎么做 |
|---|---|---|
0… | 不足一半 | 舍,保留位不动 |
1… 且后面还有 1 | 超过一半 | 入,保留位加 1 |
1 000…0(首位 1、其后全 0) | 恰好一半 | 取偶:保留位末位是 1 就加 1,是 0 就不动 |
🔴 "取偶"这一条极少触发。 只有被丢弃的部分恰好是半个末位(首位 1、其后全 0)时才用它,其余情况就是普通的 0 舍 1 入。所以顺序是先判"是不是正中间",再决定用哪条——反过来先想着取偶,就会算错。
舍入位 R 与粘位 S:判据只要两个信号,以及"取偶"的唯一理由(想弄清进位公式与硬件为什么不必留下整串丢弃位时展开)
演示(尾数只保留 4 位,就近舍入):
| 原尾数 | 保留位 | 丢弃位 | 判定 | 结果 |
|---|---|---|---|---|
0110 | 0100 | 首位 0 → 舍 | 0110 | |
0110 | 1100 | 首位 1 且后有 1 → 入 | 0111 | |
0110 | 1000 | 恰好一半,末位 0 → 不动 | 0110 | |
0111 | 1000 | 恰好一半,末位 1 → 加 1 | 1000 |
后两行的丢弃位完全相同,只因保留位末位的奇偶不同,处理就相反——"取偶"只在这两行生效。
上表的三行判定实际只用到被丢弃位串的两个信息:
- 舍入位
:紧挨保留位的第一个被丢弃位 - 粘位
:其余所有被丢弃位的逻辑或("后面还有没有 1")
设保留位末位为
为什么"中间值取偶"而不是统一进位:统一"逢中进位"会让误差单向累积——每次都往大的一侧偏,一长串运算下来结果系统性偏高。取偶让中间值一半向上、一半向下(末位是 0 还是 1 大致各半),误差期望为 0。这是"取偶"唯一的理由,与位模式好不好看无关。
七、怎么比大小
移码阶码的设计就是为了这件事:
- 先看符号位。
的一定大于 的( 除外)。 - 同为正数:直接把整个 32 位当无符号整数比——阶码在高位、尾数在低位,字典序正好等于数值序。
- 同为负数:反过来——位模式作为无符号数越大,绝对值越大,值反而越小。
第 3 条最容易翻车。稳妥的做法是把两个数的符号和真实指数都写出来再下结论。
🔴 负浮点数比大小要反过来。 正数把整个位串当无符号整数直接比就行;负数的位模式越大,值反而越小。
与 NaN 是这条捷径的两个例外——特别是 NaN 与包括它自己在内的任何数比较都不相等。
两个方向的转换各走一遍,外加 2^24+1 存不下的全过程(想核对自己的转换步骤或舍入判据用得对不对时展开)
机器数 → 真值:十六进制展开成 32 位 → 按 1 / 8 / 23 切开 → 先看阶码是不是全 0 或全 1(这一步决定走哪条公式)→ 规格化数取 1. → 写成
真值 → 机器数:绝对值写成二进制 → 规格化成
常用二进制小数:
(一)机器数 → 真值:某单精度机器数为 C154 0000H。展开成 1 10000010 10101000000000000000000:
反向验算:
(二)真值 → 机器数:把 0 10000101 00000110000000000000000:
(三)
- 二进制:
- 规格化:
——小数点后需要 24 位才写得全,而尾数字段只有 23 位,多出来的正是末尾那个 1。 - 套判据:丢弃部分是
1,首位为 1 且其后再无 1,属恰好一半;保留部分末位是0(偶),故不进位。
- 阶码
,尾数字段全 0,得 4B80 0000H。
把 4B80 0000H 读回来得到的是 int 转 float 会丢精度的原因:两者同为 32 位,但 float 拿走 8 位存量级,留给有效数字的反而更少。
三问走的是同一条路。每次都先看阶码是不是全 0 或全 1——这一步决定用规格化公式还是非规格化公式。
考点速记
- 总位数定死,阶码定范围、尾数定精度;阶码用移码,既让位串顺序等于数值顺序,又把待征用的全 0 / 全 1 推到数轴两端,偏置常数取
(127 / 1023)。 - 二进制规格化尾数最高位恒为 1 故隐藏不存(23 位字段 → 24 位有效数字),代价是表示不出 0,由此逼出整张五类取值表:阶码只决定走哪条分支,尾数决定分支内的取值;非规格化数的指数固定为
(单精度 ),与最小规格化数共用同一个指数。 - "能表示"由阶码决定、"能精确表示"由尾数决定(最大正数
vs 最大精确整数 );能精确表示 最简分数的分母是 2 的幂;就近舍入只有恰好半个末位时才取偶;负浮点数比大小要反过来。
这一节在真题里被考过的形式(下方「真题练习」逐题对应,本章题量最大的一篇):
- 给一个十六进制机器数,问它按 float 解释的值:展开成 32 位 → 按 1/8/23 切开 → 先看阶码是不是全 0 或全 1(决定走哪条公式)→ 规格化数取
、尾数前补回 1.。 - 给一个十进制数,问它的 float 机器数:绝对值转二进制 → 规格化成
→ → 尾数右边补 0 补满 23 位 → 四位一组转十六进制。 - 问单精度能表示的最小/最大正数,或能精确表示的最大整数:四个数各有各的来源,看清题面有没有"规格化""精确"这两组字——最小正数
与最小规格化正数 差 倍,最大正数由阶码定而最大精确整数 由尾数定。 - 问某个 int 值转成 float 后是否精确、或两个类型能否互相无损往返:比有效位数——int 有效位可达 31 位、float 只有 24 位,超过
的奇数存不下。 - 给一个机器数,问它按 int 或按 float 解释时的值可能是多少:同一串位分别按补码和 IEEE 754 各读一遍。
- 挑关于 IEEE 754 的错误叙述:常设的错点是"阶码全 0 表示 0""偏置常数是
""有效位是 23 位""非规格化数的指数是 "——四条全是本篇 🔴 标出来的那几处。 - 大题里做浮点数的编码与解码:步骤同上两条,但要写出每一步的中间结果(阶码字段的十进制值、尾数补隐藏位后的形式),只给最终答案通常拿不到全分。
易错:把偏置常数记成
。是 。
易错:非规格化数的指数按
算成 。它固定是 。
易错:有效位按尾数字段的 23 位算。加上隐藏位是 24 位。
易错:把"最小正数"与"最小规格化正数"混答。差整个非规格化区。
易错:负浮点数按位串顺着比大小。要反过来。
教材出处
- IEEE 754 格式、隐藏位、偏置常数取
的两个好处:袁春风《计算机组成与系统结构》第 3 版 §2.3.3 IEEE 754 浮点数标准,印刷页 p36 - 五类取值的解释(表 2.2)、非规格化数指数固定为
/ 且用于处理阶码下溢、NaN 的产生操作(表 2.3)、格式参数(表 2.4):同书 §2.3.3,印刷页 p37–p38 - 浮点数规格化的定义与左规/右规:同书 §2.3.2 浮点数的规格化,印刷页 p36
- 基数为 16 的浮点格式(IBM 370 短浮点数,尾数用十六进制原码小数、无隐藏位)与基数为 2 的格式对照:同书 §2.3.1 浮点数的表示格式 例 2.21/例 2.22,印刷页 p35
- 四种舍入方式及表 3.4 舍入示例、图 3.17 浮点数间隔(数密度):同书 §3.5.2 浮点运算的精度和舍入,印刷页 p83–p85
- 单精度最小可表示数
、规格化数个数与量级范围:袁春风《计算机系统基础》§2.3.3,印刷页 p49
相关知识
真值与机器数:四种编码的定义|浮点数的加减运算|C 语言中的数据类型与转换|进位计数制与转换