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

前两天帮人看代码,他在循环里给账户余额累加利息,跑了几十万次之后尾数悄悄飘了,对账对到怀疑人生。他一口咬定是编译器抽风,其实锅在浮点数自己身上。

计算机按 IEEE 754 用二进制存小数。0.1 和 0.2 在二进制里都是无限循环小数,压根凑不出一个干净的 0.3,真实结果是个 0.30000000000000004。单看一次误差小得可怜,可一旦进循环累加、做金额结算,或者拿 == 直接判相等,错就一层层放大了。

我早年写 C 的时候也在这种地方栽过。靠谱的做法就两条:碰钱一律用整数分或者 Decimal 来存,别让浮点沾边;判断相等改成误差阈值,abs(a

gauss_58
[链接]

早年帮人排查过同类问题,整数分这招确实靠谱。不过算利息按比例分摊那步,整数先乘后除会把零头直接抹掉,还得用Decimal兜底才稳。

duckling90
[链接]

循环里累加那个太真实 我之前尾数飘了还以为是数据库抽风 全改整数分才踏实 哈哈

sweet
[链接]

对账对到怀疑人生太真实了,这种看不见的误差最磨人,辛苦楼主

snarky_jr
[链接]

编译器这次可算沉冤得雪了。说真的,最逗的是这种坑年年有人踩,踩完还特理直气壮觉得是机器抽风,敢拿 double 数钱的那份坦然我是真服气。

oldschool__q
[链接]

那人还算走运,几十万次才飘出来,早点逮住对账还能救。我见过更闷的,一笔笔看着都对,月底合总差了几分钱,三个人翻了两天账本,才发现是某个分支里拿浮点比了大小,临界值附近的单子全漏了。
说实话
钱的事跟浮点讲不上面子…,它最靠不住。碰金额就老老实实用整数分,能省掉不少后半夜的折腾。

iron
[链接]

以前帮人理过一阵子小账本,那滋味跟你说的对账怀疑人生差不离。对方死活认定是自己算岔了,拿手机计算器按了十几遍,末了才发现一笔两块三的零头压根没记上。

你这帖子勾起我那段回忆了。其实不是什么大毛病,就是一个不起眼的小东西悄悄搁在那儿,你不理它,它跟着日子一天天膨胀。他非说是编译器抽风,可头回撞上这种事,谁都先怪机器。人嘛,总乐意把锅甩给外头。

钱的事儿还是得抠细,先把差在哪一厘弄清楚,比闷头重算一万遍管用。

newton__uk
[链接]

你最后那段被截了,我正好接着说。光写 abs(a-b) < eps 这种绝对误差阈值,在量级差很大的两个数上会失灵。比如比 1e8 和 1e8+3,eps 取 1e-9 永远判不等,可相对看误差微乎其微。金额场景因为同量级还凑合,通用的更稳做法是相对误差,或者按业务精度先 round 再判等。

前阵子翻老代码见过有人拿 == 比浮点,注释写着"应该没问题"。这种坑谁没踩过呢。

sharp
[链接]

那句"编译器抽风"真是精准还原了现场气氛,每个新手第一次撞上这事儿都这反应。我前阵子看人做报表也是浮点求和,打印出来差几分钱,查半天才发现数据库里存得本来就是float,Decimal都救不了已经被存歪的东西。楼主说的整数分方案最实在,钱这种东西从一开始就不该交给二进制去估。

theorem__fox
[链接]

他一口咬定编译器抽风的反应太真实了,我以前也见过同事对着对账差异抓瞎。

想补一个点:整数分能根治累加误差没错,但利息计算本身免不了乘除法——余额乘日利率再取整那一步就在做舍入了。到底用四舍五入还是银行家舍入(round half to even),规则不统一,跨系统对账照样翻车。所以"用整数分"只是前提,配套的舍入策略才是真得写进文档的东西。

至于 abs(a-b)<阈值 这套,从某种角度看更像给浮点域兜底,钱的事与其设阈值,不如干脆不进浮点,直接整数比大小来得干净。

legacy_2004
[链接]

我年轻的时候也以为机器算账万无一失,后来才明白,钱这东西差一分都不行。循环累加最磨人。

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