@CompSciFact: 浮点数是一种泄漏的抽象
摘要
一篇文章解释了为什么浮点数是泄漏的抽象,涵盖精度限制、减法问题和溢出/下溢,并引用了Goldberg的经典论文。
查看缓存全文
缓存时间: 2026/07/31 06:50
浮点数是一种泄漏的抽象 https://t.co/xDWVo6LsyJ
浮点数:一种泄漏的抽象
来源:https://www.johndcook.com/blog/2009/04/06/numbers-are-a-leaky-abstraction/ Joel Spolsky 创造了“泄漏的抽象”这一术语(https://www.joelonsoftware.com/articles/LeakyAbstractions.html),用来描述那些通常能让你免于混乱细节、但有时会失效的编程概念。完美的抽象是一个你永远不必打开的黑盒。泄漏的抽象是一个你偶尔不得不打开的黑盒。
浮点数,即计算机对实数的表示,就是一种泄漏的抽象。它们表现得非常出色:你通常可以假装浮点类型就是数学上的实数。但有时你不能。这种抽象会泄漏,尽管不常发生。
我所听到的关于机器数局限性的解释大多很学究气。“浮点数只有有限个,所以它们不可能很好地表示实数。”这没什么帮助。它没有解释为什么浮点数实际上确实能足够好地表示实数以满足大多数应用,也没有指出这种抽象可能在哪些地方泄漏。
一个标准浮点数大约有 16 位十进制精度,最大值约为 10^308,即 1 后面跟 308 个零。(根据 IEEE 754 标准,即典型的浮点实现。)
十六位小数是很大的精度。几乎没有哪个测量量能精确到接近这个程度。例如,牛顿万有引力定律中的常数只知道六位有效数字。电子电荷已知到十一位有效数字,比牛顿引力常数精确得多,但仍然少于浮点数。那么什么时候十六位数不够用呢? 一个问题是减法。其他基本运算——加法、乘法、除法——都非常精确。只要不出现上溢或下溢,这些运算的结果通常都能精确到最后一位。但减法可能从完全精确到完全不精确。如果两个数有 n 位相同,那么它们的减法可能会损失多达 n 位的精度。这个问题可能会在其他计算的中间意外出现。例如,参见这篇关于计算标准差的文章。
那上溢和下溢呢?你什么时候需要大于 10^308 的数? 通常你不需要。但在概率计算中,例如,除非你很聪明,否则你总是需要它们。在概率中,常常要计算一个中等大小的数,它是一个天文数字般的大数与一个无穷小的数的乘积。最终结果能很好地放进计算机,但中间数可能因上溢或下溢而放不进去。例如,大多数计算机上的最大浮点数介于 170 的阶乘和 171 的阶乘之间。这么大的阶乘经常出现在应用中,通常与其他大阶乘构成比值。
通常你可以心安理得地忽略浮点运算的细节,但有时你却不能。深入学习的一个好去处是 David Goldberg 的论文《每个计算机科学家都应该了解的浮点运算》。
更新:参见后续文章,浮点数的解剖。
更多关于浮点计算的内容
相似文章
中间浮点精度
本文探讨了C++代码中的中间浮点精度如何依赖于编译器设置、CPU标志和架构,尤其是在x87 FPU上,以及这如何影响性能和计算结果。
@charles_irl: 低精度浮点数很奇怪。我一直在推理/训练之外使用它们来建立直觉…
一条推文介绍了微缩放/块量化格式(如NVFP4和MXFP4)的可视化工具,解释了这些低精度浮点数的工作原理以及它们在LLM推理中减少内存带宽需求的应用。
浮点数不与自己一致
开发者发布了 `exact-poly`,这是一个使用精确整数算术而非浮点数的二维几何库,旨在消除因 IEEE 754 实现差异导致的跨平台重现性问题。
大型语言模型在浮点错误分类上的基准测试
本文介绍了InterFLOPBench,这是一个用于评估LLM在C代码中检测浮点错误的基准测试,发现最近的模型取得了较高的F1分数,但性能因错误类型而异。
RISC-V 与浮点运算
关于 RISC-V 架构浮点功能及更新的报告。