浮点数的存储 —— IEEE 754 标准
标准概述
IEEE 754(Institute of Electrical and Electronics Engineers 754)是目前最通用的浮点数存储标准,几乎所有现代 CPU 和编程语言都遵循此标准。
浮点数的数学表示
任何浮点数都可以写成科学计数法的形式:
| 符号 | 名称 | 说明 |
|---|---|---|
| 符号位(Sign) | 0 = 正数,1 = 负数 | |
| 尾数(Mantissa / Significand) | 规格化后,整数位恒为 1,只需存小数部分 | |
| 指数(Exponent) | 实际指数经过偏置处理后存储 |
整数位的 1 不需要存储,称为隐含位(hidden bit),可以省一位存储空间。
两种精度格式
| 单精度(float,32位) | 双精度(double,64位) | |
|---|---|---|
| 符号位 | 1 位 | 1 位 |
| 指数位 | 8 位 | 11 位 |
| 尾数位 | 23 位 | 52 位 |
| 指数偏置值 | 127 | 1023 |
存储布局(以单精度为例)
31 30 23 22 0
┌───┬────────────┬────────────────────────┐
│ S │ Exponent │ Mantissa │
│1位│ 8位 │ 23位 │
└───┴────────────┴────────────────────────┘
指数的偏置存储(Biased Exponent)
指数不直接存补码,而是加上一个**偏置值(Bias)**后存储为无符号整数:
- 单精度 Bias = 127,指数范围:(实际存储 1~254,0 和 255 保留)
- 双精度 Bias = 1023,指数范围:
为什么用偏置而不用补码? 偏置表示法可以直接用无符号整数比较大小,硬件实现更简单。
完整转换示例
将 转为 IEEE 754 单精度
Step 1:转二进制
Step 2:规格化
Step 3:填各字段
| 字段 | 值 | 说明 |
|---|---|---|
| 符号位 S | 1 | 负数 |
| 真实指数 | 3 | |
| 存储指数 | ||
| 尾数 M | 10010100000000000000000 | 去掉整数位的 1,补零到 23 位 |
结果:
1 | 10000010 | 10010100000000000000000
十六进制:0xC1480000
特殊值
| 存储指数 | 尾数 M | 含义 |
|---|---|---|
| 全 0(0) | 全 0 | |
| 全 0(0) | 非零 | 非规格化数(极小值,整数位为 0) |
| 全 1(255/2047) | 全 0 | (无穷大) |
| 全 1(255/2047) | 非零 | NaN(Not a Number,非法运算结果) |
精度问题
浮点数不能精确表示所有十进制小数,例如 在二进制中是无限循环小数:
这是浮点运算产生误差的根本原因,不是 bug,是规范本身的限制。
>>> 0.1 + 0.2
0.30000000000000004 # 不等于 0.3