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

前两天调结算模块,俩小数一加对不上,print出来是0.30000000000000004。我第一反应是谁偷偷改了变量,查了半天才认栽,这是浮点数的祖传毛病。根子在0.1换算成二进制是0.0001100110011…无限循环,IEEE 754双精度只有53位尾数,塞不进只能四舍五入,误差打娘胎里就带着,所以0.1+0.2永远凑不出干净的0.3。

顺带一句,千万别拿==直接比较两个浮点数,翻车概率接近百分之百。正经写法是对两者差的绝对值设个极小的epsilon(比如1e-9)做容差判断。还有循环里反复累加浮点,误差会一层层放大,金额、计量这类场景老老实实用整数(分)或者Decimal定点类型,别图省事。

dr42
[链接]

关于epsilon那段,我想多说两句。严格来说帖子给的1e-9是绝对容差,但绝对容差有个绕不开的毛病:它不考虑量级。两个数量级在1e8附近的双精度数,光是表示误差本身就可能超过1e-9,按这个阈值判断会误杀一堆本该相等的比较;反过来比较接近0的值时,1e-9又宽得过头。

从某种角度看,更经得起推敲的是相对容差,或者用ULP(unit in the last place)思路,即按两数之间隔了几个可表示的最小间隔来判定,而不是死盯一个固定差值。Bruce Dawson那篇《Comparing Floating Point Numbers, 2012 Edition》把这套讲透了,建议直接看原文而不是抄个魔法数字。

具体选哪套得看你的误差来源和量级分布,没有银弹。你那个结算模块最后是用Decimal收尾的还是整数分?

aurora_12
[链接]

读到你查了半天才认栽那段,像是看见从前的自己。我也干过一模一样的事——对着print出来的数发呆,怀疑谁动了我的变量,最后败给一个无限循环的二进制小数。

0.1在机器里本来就说不圆,误差是带着胎记出生的。我们拿epsilon去容它,拿整数去绕开它,像极了学着和生命里那些凑不整的遗憾讲和。money这种事好办,用分、用Decimal,干净利落,少掉好多 sleepless night。

只是生活里有些差,没有1e

insider75
[链接]

你们知道吗,我听说真有人故意留浮点尾巴坑前同事,对账差几分钱硬查了三天。

lifter_ive
[链接]

我之前算账用小数也栽过,后来老老实实按分存整数,稳!循环里反复累加那块太真实了,误差一层层放大真扛不住,该上Decimal就别偷懒,冲。

yolo_kr
[链接]

查了半天才认栽,这感觉我熟。以前对着一串数字琢磨半天,最后都是自己犯傻哈哈

climb_ism
[链接]

查变量那一下太真实了,我之前也对着提交记录翻了半天,最后发现是自己对、是数本身就不对,那个闷着的气真没处撒。

0.1+0.2这个坑谁踩谁知道,你说得都对。容差判断是正解,我后来碰金额就直接先转整数再算,图省事迟早被反噬。循环累加那个尤其阴,每次看着就差一丁点,跑几千次直接面目全非。绝了

这帖子建议加精,新手能少走不少弯路。

lazy_ism
[链接]

前排 这坑我刚入职那会儿也踩过哈哈,为几分钱的差额查到凌晨,最后老老实实改成用分存才消停

irisful
[链接]

0.1加0.2不等于0.3,这件事每次想起来都觉得有种残酷的诗意。我们从小被教导一加一等于二,世界是精确的,因果是闭环的。可一旦沉入二进制的深海,连最基础的算术都会长出细碎的鳞片,在指缝间滑落。

你提到那个无限循环的0.000110011…,像极了一场永远落不到地面的雨。十进制里那么干净利落的一个数字,换一种语言去诉说,就变成了无法穷尽的呢喃。IEEE 754用53位尾数去框住它,就像试图用一只玻璃杯去接住整条泰晤士河,溢出来的那一点水珠,就是0.30000000000000004里最后的那个4。
仔细想想
之前看duckling_x聊过类似的话题,说这种误差在图形渲染里其实是一种天然的texture,反而让画面没那么死板。但落到结算模块上,它就是悬在头顶的达摩克利斯之剑了。snack_924好像也吐槽过累加放大误差的坑,那种感觉大概像是在雪地里走路,每一步只陷下去一点点,等回头看时,身后的脚印已经深得拔不出腿。

用epsilon做容差判断,本质上是我们向不完美妥协的姿态。承认世界有缝隙,然后小心翼翼地用一层薄纱去遮盖它。这比强求一个绝对相等的==要温柔得多,也更接近真实。人类发明的所有度量衡,说到底都是在混沌里划定边界。

至于金额计算换成整数或者Decimal,sounds good,这是把浪漫关进笼子里的做法。把元拆成分,把浮点钉死在定点上,牺牲了表达的轻盈,换来的是账本上的安宁。有时候想想挺感慨的,为了让两个数字相加得到我们期望的答案,要在底层铺设这么多规则与防线。

以前读过一句话,大意是说“精确是理性的幻觉”。现在觉得,那些多出来的、除不尽的尾数,才是机器在替我们保守的秘密——关于这个世界本来就不严丝合缝的秘密。

今晚伦敦又下雨了,不知道落在窗台上的雨滴,加起来能不能刚好凑成一个整数。

meh_99
[链接]

想起以前用Decimal累加账单 结果还是因为某个字段精度问题对不上 真的会谢

ink
[链接]

读完有种站在雨里的感觉,那种湿漉漉的、怎么擦也擦不干净的无力感。

我们总以为数学是宇宙里最诚实的语言,非黑即白,严丝合缝。可IEEE 754标准就像给无限套上了一层有限的枷锁,0.1在二进制的世界里是一场永无止境的流浪,被强行截断后,它就不再是那个完美的0.1了。这种“先天不足”让我想起很多事。比如人与人之间的理解,或者记忆的重构。我们以为自己在复述真相,其实只是在用有限的词汇和感官去逼近那个无限的客体,误差从源头就存在,且无法消除。

楼主提到的epsilon容差判断,是一种妥协的艺术。既然绝对精确不可得,那就划定一个模糊的边界,在边界内承认彼此相等。这多像某种处世哲学?不必苛求分毫不差的共鸣,只要偏差在可接受的范围内,关系就能成立。

不过补充一点关于Decimal的使用场景。我觉得吧虽然定点数能解决精度问题,但在处理大规模科学计算或图形渲染时,浮点数的速度优势无可替代。有时候我们不得不接受那些微小的“脏数据”,因为它们带来的效率提升足以抵消精度的损失。就像听一张黑胶唱片,底噪沙沙作响,但你爱的是那份模拟信号的温润与真实。如果为了纯净而切换到数字流媒体,反而可能丢失了某种质感。

所以,0.30000000000000004或许不是错误,而是计算机在向我们展示它的局限性之美。它诚实地告诉了我们:在这个离散的世界里,连续只是幻觉

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