揭开浮点数的面纱 —— Bartosz Ciechanowski

查看原文 HN 讨论

文章摘要

这是 Bartosz Ciechanowski 2019 年的经典长文,时隔多年仍被反复送上 HN 首页——原因显而易见:它把 IEEE 754 浮点数从最朴素的”二进制科学计数法”一步步推导出来,配上完全可交互的 SVG 演示,让本科课本里通常只能死记硬背的细节变得可视、可玩、可理解。

文章从基础设定开始:浮点数本质上就是二进制下的科学计数法,形如 ±1.xxxxx × 2^n,区别在于尾数(significand)位数和指数(exponent)范围都被硬件强行限制了。作者按 IEEE 754 单精度 float 的 32 位布局逐字段拆解:

字段排列顺序”符号 → 指数 → 尾数”也不是随便选的:它使得相邻浮点数的二进制表示也相邻,于是把浮点数当成整数来比较大小、用整数加法做”取下一个可表示浮点数”等操作都成立——这是很多游戏引擎、数值库底层小技巧的根基。

接下来文章重点讲精度局限。0.2 这种十进制看似简单的数,在二进制里是无限循环小数,必须截断舍入;从第 25 位有效二进制位开始就放不下了。float 能精确表示的最大连续整数是 2²⁴ = 16,777,216,超过这个范围每隔几个整数才会有一个能被精确表示,所以用 float 存大整数是危险的。

特殊值部分作者讲得非常细:+0.0−0.0 同时存在并保留方向信息(在某些数值库里有意义);溢出会变成 ±∞,且无穷大的算术规则符合直觉;NaN(Not a Number)有 800 多万种位模式,而且 NaN != NaN 永远成立——这是判断 NaN 的常用技巧,也是踩坑大户。Subnormal(亚正常数)让 2⁻¹²⁶ 以下的更小数仍能被表示,代价是精度下降,配合”渐进下溢(gradual underflow)”避免突变。

文章独有的特色是它的配套站点 float.exposed:你输入任意十进制数,立刻能看到它被压缩成 float 后的位级表示、与最近可表示值的偏差、以及连续浮点数之间的间距如何随量级指数级膨胀的可视化图。文末作者推荐了 Bruce Dawson 的浮点系列博客和 Goldberg 的经典论文 What Every Computer Scientist Should Know About Floating-Point Arithmetic,作为延伸阅读。

HN 评论精华

  1. subset(顶贴):第一眼看到时还以为 Bartosz 又出新文了,结果是 2019 年的旧作,标题应该加 [2019] 才对。这条吐槽下面引出了关于作者状态的讨论——macintux 指出 Bartosz 过去每年发 1~5 篇质量极高的长文,但今年和去年都没有更新;9dev 解释这种深度交互式文章工作量极大,他不一定停笔,可能只是阶段性休息。HN 的高赞之声基本是”想念他下一篇”。

  2. rurban:技术补充——TinyCC(tcc)也支持二进制浮点字面量扩展,给了 GitHub 链接示例 long double la0 = 0B.110101100P12L;。这是 C 扩展里少见的功能,方便在源码层面直接写出位级表示。

  3. throw0101a 引 NASA JPL:分享了 NASA JPL 关于 π 精度的著名科普——星际导航的最高精度计算只用 3.141592653589793(15 位),而要用 π 算”已知宇宙半径(460 亿光年)的圆周长精确到一个氢原子直径”,38 位(37 位小数)就够了。这条评论引出了bombcarua709的讨论:”数字精度容易超过物理精度”,但计算中误差可能累积——快速累加大量浮点数时,精度需求可能远高于单次结果所需。

  4. adampunk:提醒大家试试用 3.141592653589793 计算大幅角的 sin / cos。这是浮点圈著名的”灾难性抵消”陷阱——当输入角很大时,π 的有限精度被乘上巨大整数倍,残差被放大,结果可能完全不可信。这就是为什么数值库的 sin 内部要做 range reduction

  5. amelius / gozzoo:指出文章应当增加一节关于深度学习里量化(quantization)的新内容——FP16、BF16、FP8、FP4 已经是大模型推理的主战场,浮点格式的选择直接决定了显存占用和精度损失。gozzoo 提供了一篇 ngrok 关于 quantization 的博客作为参考。这反映出 2019 年的浮点扫盲文在 LLM 时代有了新的应用场景。

  6. 整体氛围:评论区罕见地几乎没有反对意见,绝大多数人都在赞叹 Ciechanowski 的可视化质量、推荐他的其他作品(GPS、相机、灯光、傅立叶变换等系列)。许多人把他与 3Blue1Brown 并列,认为他的网页交互演示是”互联网上少有的、真正能让人理解抽象数学/计算机概念的资源”。