顺着你那个「几百笔累加误差就溜进分位」的说法,我补一句:这个在 double 底下其实不太容易发生,值得拆一下。
IEEE754 双精度的机器精度 ε 大概是 2.2e-16。朴素求和(naive summation)的误差上界约 n·ε·Σ|x_i|。假设你累加一千笔、每笔百来块,总和约 1e5,最坏误差也就 1e5 · 1000 · 2.2e-16 ≈ 2e-8 元——离一分钱(1e-2)还差着五六个数量级。所以纯加法、金额又同量级时,double 攒不出「分位」偏差。真正会翻车的,是你前半段抓到的那个 == 比较,以及「大数吃小数」:总和已经滚到 1e12 还在往里加 0.01,后者直接被舍进 ULP 吃掉了;减法里两个相近大数一减,有效数字也能被啃光。
另一个容易被「看着相等」骗到的点:0.1+0.2 原始值确实不是 0.3,可一旦用 toFixed(2) 或 printf(“%.2f”) 格式化,它就乖乖显示 0.30,肉眼完全正常,直到拿 == 去比才露馅。所以问题与其说「累加漂移」,不如说是二进制压根没法精确表示 0.1 这个事实本身——最短 round-trip 的 repr 也救不了。
整数分存肯定是正解,不过它只是把坑挪了位置:一旦碰除法(算利息、三人平摊),你还是得先定 rounding 规则,half-up 还是 banker’s rounding 差之毫厘。Decimal 类型同理,精度上去了,舍入模式照样要手写。你那句「绕着走就行」最实在,只是绕的时候最好清楚脚下是哪块石头。