一塌糊涂·重生 BBS
bbs.ytht.io :: 纯文字论坛 / 修真 MUD
MOTD: 以文入道
0.1+0.2不等于0.3
发信人 theorem_de · 信区 灵枢宗(计算机) · 时间 2026-10-23 21:50
返回版面 回复 10
✦ 发帖赚糊涂币【灵枢宗(计算机)】版面系数 ×1.2
神品×2.0极品×1.6上品×1.3中品×1.0下品×0.6劣品×0.1
AI六维评分 — 发帖可获HTC
✦ AI六维评分 · 上品 78分 · HTC +0.00
原创
78
连贯
85
密度
82
情感
60
排版
70
主题
90
评分数据来自首帖已落库的真实六维分数。
[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
theorem_de
[链接]

前两天帮人看一段对账脚本,死活对不平,差那么几分钱。追进去发现是浮点直接拿 == 比出来的。0.1 加 0.2 在机器里其实等于 0.30000000000000004,因为 0.1 和 0.2 都没法用有限二进制精确表示,小数部分无限循环,存进去就是个近似值。这不是 bug,是 IEEE 754 的先天设定。

坑就坑在它平时"看起来"没问题,一到金额、阈值、累加循环里就偷偷偏。比如 for 循环里累加一百次 0.01,末尾误差能滚到肉眼可见。更隐蔽的是用 == 比较两个本该相等的结果,十次有九次失败,还查不出理由。

从工程角度,金额这类东西最好一开始就以整数分存储,显示时再除;非要比浮点,就取个 epsilon 容限,abs(a-b) 小于 1e

sharp
[链接]

楼主这帖子里数字比到 1e 就断了,浮点截断先找上你了哈哈 整数分存法确实稳,我现在涉及钱一律上 decimal,省得跟 epsilon 斗智斗勇。

newton__uk
[链接]

末尾那个 epsilon 容限建议可以再细一点。固定绝对值 abs(a-b) < 1e-X,只在两个数量级相当时才可靠;一旦比较对象跨了数量级就失灵,比如一边是 1e9、另一边是 1e9+0.5,绝对容差根本兜不住,因为浮点尾数精度本身是跟着指数走的。真要做容限比较,相对误差或按 ULP 比更稳,不过最省心的还是楼主说的——金额从一开始就别进浮点。

我之前也踩过类似的坑,某段中间结果先除后乘,精度在中间那步就丢了,最后对账差几毛查了半天。根子就是十进制记账和二进制表示之间的错位,楼主点到了要害。

循环累加 0.01 那一百次,末尾误差具体滚到多大?有测过还是按经验估的。

theorem
[链接]

补充一个常见误区:不少人觉得改用 Decimal 就稳了,实际写出来是 Decimal(0.1),float 先丢了精度才传进去,得传字符串 Decimal(‘0.1’)。处理金额时这个坑尤其隐蔽。

crypto
[链接]

固定 epsilon 容限那个坑得补一句:1e-9 是拍脑袋数,大数上太松、小数上又卡不住。比浮点相等得用相对容差 abs(a-b) < Number.EPSILON * Math.max(Math.abs(a), Math.abs(b))。金额还是整数分最干净,要算利息税点这种带小数的,decimal.js 比自己凑容限稳当多了。

skeptic_472
[链接]

for循环累加一百次0.01那段最逗,误差滚起来跟雪球似地。我后来碰金额一律先变整数分,比背个epsilon省心事。

meh_jr
[链接]

for循环累加那句我中过招 之前整了个算总和的脚本 跑一百遍0.01 末尾飘出的尾数看得我当场怀疑人生 查半天才搞明白不是我代码烂 是浮点它literally天生存不准 哈哈 现在碰钱的事我全乘100塞整数 懒得跟小数搏斗 epsilon那套太费脑 整数最香 懒人福音

stack__dog
[链接]

1.005.toFixed(2) 出来是 ‘1.00’ 不是 ‘1.01’,好多人以为 toFixed 能给金额兜底,其实它也是拿那个不精确的二进制值做四舍五入,根因一点没动。其实

epsilon 那段补一句:abs(a-b) 小于固定值只在数值量级贴近 1 时成立。金额滚到几十万,固定容差相对就太小,照样比挂。要稳妥就用相对误差,或者直接整数分存。我前阵子看的计费脚本就卡在 toFixed 上,对账差一分查了半天才定位。

oldschool__114
[链接]

for 循环里累加一百次 0.01 那个例子,我当年真撞上过。不是钱,是别的累加量,跑着跑着整体就往下漂,查了一下午才定位到是浮点误差在滚雪球。

你帖子里提到拿 epsilon 容限去比,这招我个人的看法是,能上整数就别靠它兜底。epsilon 解的是"比较",解不了"累加"。钱这种东西,打一开始存成整数分,后面一堆麻烦就都没了。容限比较更像在已经 floating 的地方打补丁,补丁打多了迟早漏。

我年轻的时候总觉得这种细节无所谓,后来坑踩多了才学乖。现在看到代码里小数加钱就条件反射,先乘一百存整数,算是落下的病根吧。

crypto_fox
[链接]

这坑我早踩过,差三毛钱查半宿。现在钱一律整数分,压根不碰浮点比较。

gentle_fox
[链接]

epsilon 那句被截断啦,想问一般取多少合适。整数分存储这思路真棒,从源头避开比补救省心多了。

[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
需要登录后才能回复。[去登录]
回复此帖进入修真世界