定点数与浮点数表示(IEEE 754 标准)
🎯 学习目标
- 理解定点数的基本思想(为浮点做铺垫)
- 掌握 IEEE 754 单精度(32位)浮点数的结构
- 能手动将十进制小数转换为 IEEE 754 格式
- 理解 为什么
0.1 + 0.2 != 0.3 - 了解特殊值:无穷大(∞)、NaN、非规格化数
一、为什么需要浮点数?
整数可用补码完美表示,但现实中有大量小数:
- 科学计算:
3.1415926 - 金融:
99.99 - 图形:坐标
(1.5, -2.3)
如果用固定小数点位置(比如始终保留2位小数),叫 定点数(Fixed-Point):
- 优点:硬件简单,运算快
- 缺点:范围小、精度固定(无法同时表示
0.000001和1000000.0)
【Q&A】为什么定点数无法同时表示极小数和极大数?
因为定点数的小数点位置在硬件中是固定的。例如,若用32位表示,你必须预先分配多少位给整数部分、多少位给小数部分。
- 表示
1000000.0需要约20位整数部分;- 表示
0.000001需要约20位小数部分;
但总共只有32位,无法兼顾。
而浮点数通过“阶码”动态调整尺度,用同一格式覆盖极大范围和高精度。
→ 所以需要 浮点数(Floating-Point):小数点位置可以“浮动”,类似科学计数法!
二、科学计数法 → 浮点数思想
十进制科学计数法:123.45 = 1.2345 × 10²
二进制科学计数法:5.75₁₀ = 101.11₂ = 1.0111 × 2²
浮点数就是把一个数拆成三部分:
数值 = (-1)^S × (1.M) × 2^(E - Bias)
- S:符号位(0正,1负)
- M:尾数(Mantissa / Fraction),表示有效数字
- E:阶码(Exponent),表示指数(带偏移)
✅ 这就是 IEEE 754 标准的核心!
三、IEEE 754 单精度(32位)格式
| 位段 | 长度 | 含义 |
|---|---|---|
| S(符号) | 1 位 | 0 = 正,1 = 负 |
| E(阶码) | 8 位 | 存储 指数 + 偏移量(Bias) |
| M(尾数) | 23 位 | 存储小数部分(隐含前导1) |
💡 偏移量(Bias):单精度用 127,所以实际指数 = E - 127
🌟 关键技巧:隐含前导1(Hidden Bit)
- 规格化数(Normalized)的二进制形式总是
1.xxxxx - 所以 IEEE 754 不存这个“1”,只存小数部分
xxxxx,省1位,提高精度!
【Q&A】单精度是否等于“1位整数 + 多位小数 + 偏移”?
是的!更准确地说:
单精度将实数表示为 二进制科学计数法(-1)^S × 1.M × 2^E,然后:
- 符号 S 存 1 位;
- 尾数只存 M(23位小数部分),前导
1.是隐含的;- 阶码存 E + 127(8位无符号整数)。
这三部分组成32位,实现高效、统一的浮点表示。
四、动手:十进制 → IEEE 754(单精度)
例:+5.75
- 转二进制:
101.11 - 规格化:
1.0111 × 2²→ M =0111..., E真实 = 2 - 阶码存储:2 + 127 = 129 →
1000 0001 - 组合: 0 10000001 01110000000000000000000
五、为什么 0.1 + 0.2 != 0.3?
0.1₁₀ = 0.0001100110011...₂(无限循环)- IEEE 754 只能存 23位尾数 → 必须截断/舍入
- 内存中存的是 近似值 ≈ 0.10000000149…
- 两个近似值相加 ≠ 0.3 的近似值
✅ 在 Python 中:
1 | 0.1 + 0.2 |
💡 启示:永远不要用 == 比较浮点数!应使用 abs(a - b) < epsilon
六、IEEE 754 单精度(32位)
| 部分 | 位数 | 说明 |
|---|---|---|
| S | 1 | 符号位(0 = 正,1 = 负) |
| E | 8 | 阶码(Exponent),偏置值 Bias = 127 |
| M | 23 | 尾数(Mantissa/Fraction),隐含前导 1 |
💡 小知识:实际数值计算公式为
$
(-1)^S \times (1.M) \times 2^{E - 127}
$
其中1.M表示二进制小数(如1.101)。
示例:将十进制数 5.0 转换为 IEEE 754 单精度
转二进制:
$ 5.0_{10} = 101.0_2 = 1.01_2 \times 2^2 $确定各字段:
- S = 0(正数)
- E = 2 + 127 = 129 → 二进制
10000001 - M =
01后补零至 23 位 →01000000000000000000000
最终 32 位表示:
1 | 0 10000001 01000000000000000000000 |
七、双精度(64位)简介
| 部分 | 位数 | 说明 |
|---|---|---|
| S | 1 | 符号 |
| E | 11 | 阶码(Bias = 1023) |
| M | 52 | 尾数(隐含前导1) |
精度:≈15 ~ 17 位十进制
范围:≈ ±10³⁰⁸
编程语言中 double 类型即为此格式