浮点数的机器表示
理清 IEEE 754 每个 bit 的作用,搞懂精度损失从何而来
按 空格/→ 演示下一步
全部页面点击任意一页,跳回舞台从这页播放
浮点数的机器表示
理清 IEEE 754 每个 bit 的作用,搞懂精度损失从何而来
为什么需要浮点数
测量一片叶子的长度是 3.2 厘米,称一颗草莓重 12.5 克——这些带小数点的数字,整数表示不了。
尾数对应有效数字,指数对应数量级,基数从10换成2
浮点数的三要素
上一页我们看到,计算机不能像写数学那样随手点个小数点。要把一个小数塞进有限的二进制位里,必须把它拆成三件事:谁负责正负、谁负责量级、谁负责精度。
±M×B^E:正负号对应符号位,E 对应指数位,M 对应尾数位
浮点数存储结构
单精度32位与双精度64位的位布局图
IEEE 754 标准概述
上页看到 32 位切分成 1 位符号、8 位阶码、23 位尾数——但凭什么是这个切分?因为背后有一个统一江湖的标准。
以前各厂商各做各的,统一后才能跨平台互通
浮点数编码四步骤
把一个十进制实数变成 IEEE 754 编码,要依次过四道关。
编码实例:-6.5
手把手演示 -6.5 的完整编码过程
编码实例:0.1 的秘密
用 Python 揭开 0.1 的机器真相:为什么 0.1 + 0.2 不等于 0.3?
高亮行依次演示:① 0.1+0.2≠0.3 的现象;② 0.1 的真实存储位 0x3fb999999999999a;③ 解出符号/阶码/尾数三段;④ Decimal 还原十进制真值,证明 0.1 从来不是精确的 1/10。
规格化表示
编码 -6.5 时我们写了 1.1011 × 2^2,为什么必须把整数部分强行凑成 1?这不是格式洁癖,而是 IEEE 754 用来"偷精度"的核心设计。
都规定系数落在 [1, 进制) 区间,保证同一数只有一种标准写法
非规格化表示
上一页讲了规格化数的最小值是 2^(-126)。那 0 到 2^(-126) 之间真的没有数?规格化在这里设了门槛——次正规数就是跨过门槛、填满这片空白的角色。
原本 1kg 以下无法读,加小刻度后 0.5kg 也能读;次正规数让 2^(-126) 以下的数也能区分
规格化与非规格化的边界
从0到规格化区,两个边界点紧邻,间距等于正常步长。
精度与有效位数
上一页 0.1 算出来已经不再是 0.1,这背后就是「精度」在作怪。尾数 24 位听起来挺充裕,可它真能给你 24 位精确度吗?
尺子刻度固定;量短物精度高、量长物精度低,有效位数取决于被测物大小
浮点数的表示范围
从正零出发向右:非规格化→规格化→有限最大→溢出无穷;左侧镜像。
特殊值:无穷大与 NaN
学完表示范围,自然会追问:计算结果跑出范围怎么办?比如 1÷0、0÷0。IEEE 754 的解法很优雅——把『指数全 1』本该作废的编码,专门留给两个特殊值兜底。
超速时车还能开(∞ 仍可继续运算);故障灯一亮,后续读数都不可信——正如 NaN 污染一切
舍入模式
上页编码 0.1 时,我们悄悄把无限二进制截到 23 位。但 IEEE 754 没简单说「五入」,而是给了 5 种模式。真实值恰在两个可表示数的正中间——选哪边?
总偏一个刻度会系统偏差;选偶数刻度对称,长期平均误差趋零
float 与 double 的定义
用 <float.h> 的宏与 printf 格式说明符,把机器参数打印出来对照看。
FLT/DBL_EPSILON 把上一页"精度"量化成具体数字;f 后缀决定字面量类型;%e/%g 对应科学计数法与最短表示。
位级操作验证
用 union 让 float 与 uint32_t 共享同一段内存,直接看到 IEEE 754 的位模式。
union 让 float 与 uint32_t 共用 4 字节;写入浮点后用十六进制、二进制与位运算直接读出符号位、阶码、尾数字段,与 -6.5 的手工编码完全对得上。
整型与浮点型对比
一段 32 位内存,存整数和存小数走的路径天差地别——C/C++ 里那些隐式转换 bug,往往就藏在这。
- 补码定点存储,位与数值直接对应
- CPU 原生指令最快,开销最小
- 范围均匀离散,等步长
- 精确无误差,整数一一对应
- IEEE 754 分段:符号+指数+尾数
- 需 FPU 协助,通常更慢
- 极广但非均匀,近 0 处密集
- 存在舍入误差,0.1 都存不准
自测三题
验证对浮点数核心概念的理解
核心要点回顾
- ✓浮点 = 符号+阶码+尾数 的离散编码,用精度换范围
- ✓IEEE 754 用规格化让精度均匀,非规格化平滑到 0
- ✓0.1 不可精确:浮点运算是离散采样,非连续数学
- ✓浮点 ≠ 实数:比较看差值、累加顺序敏感、溢出变 ±∞
- ✓编码四步:符号→偏置阶码→隐含位+尾数→拼接
课后思考
先自己琢磨,再对照参考答案看思路对不对。
参考答案二进制规格化后小数点前必为 1,省下这一位可多 1 位精度——正是 IEEE 754 用 23+1=24 位精度的由来。
参考答案0.1、0.2 的二进制是无限循环,只能用 52 位近似;两次近似相加,误差累积放大。这不是 bug,是设计取舍。
参考答案精度降到约 3-4 位十进制,但单位存储可存更大范围、计算更快。GPU 着色器、早期图形 API 就常这么做。