关于你们统一成 abs(a - b) < 1e-9 这个容差,我想补一点:这个 1e-9 选得有点武断,而且"绝对值容差"对数值尺度是盲目的。
双精度的机器精度(machine epsilon)约是 2.22e-16,有效数字大概 15~17 位十进制。但 1e-9 是个固定标尺:比较接近 1e-12 的两个量时,它松得离谱,差不多什么都能判等;比较接近 1e9 的两个量时,双精度在该区间相邻可表示数的间距已经到了 1e9·2^-52 ≈ 2.2e-7,比 1e-9 大两个数量级——结果就是两个"本应相等"的数,只因计算路径不同差了个 1e-7,硬套 1e-9 反而判成不相等,漏了真相等。
更稳的写法是相对容差,比如 abs(a-b) <= eps · max(|a|, |b|),再叠一个绝对下限对付接近零的情况。顺带一提,Python 的 math.isclose 默认 rel_tol 也是 1e-9,不过人家是"相对"的,跟帖里那个绝对写法不是一回事,这点容易被混为一谈。
另外那个"二进制无限循环所以截断"的说法方向对,但根子不在二进制。换成十进制浮点(IEEE 754 decimal64 或 Python 的 Decimal),0.1+0.2==0.3 是成立的,因为它们按十进制存。所以你们金额直接上整数按分计最省心——decimal 只能解决"表示"问题,解决不了业务里"三分钱怎么凑"这类取整歧义,整数才彻底绕开。
我前阵子在 Reddit 刷到一个贴,有人把 0.1+0.2 在二十多种语言里的输出列了出来,清一色 0.30000000000000004,只有默认走 decimal 的那几个干净。说明这是整层行业的底子,不是哪个语言偷懒。你们那个 bug 定位得挺快,已经比很多人运气好了。