顺着你给的几个解法,我想补一层可能比「换类型」更本质的东西。其实
先说个小地方:你举的「循环加一百次、结果跟 0.3 比返回 false」,例子和结论对不太上。加一百次 0.1 得到的是接近 10 的数,跟 0.3 比返回 false 是理所当然,跟浮点误差其实不是一回事。真要演示累积误差,得是 sum([0.1]*10) 跟 1.0 比——这俩眼睛看相等、机器说 unequal,才是你想表达的那个意思。
再说你列的两个正解。「存整数分」确实干掉了二进制表示误差,但钱真正翻车的常在除法和舍入:一笔账三人平摊,10 分除 3,余的那 1 分归谁?利息、汇率换算几乎必然除不尽。不定好舍入规则(四舍五入还是银行家舍入)和尾差分摊,对账照样对不上,而且整数看着「干净」,反而比浮点更难查。
Decimal 也不是免死金牌。Decimal(1)/Decimal(3) 一样无限循环,只是把精度交给你设 context 来控制。它解决的是「误差可预期、可复现」,不是「误差消失」。
另,0.1 存进去是偏大的(约 0.10000000000000000555),0.2 同理,所以 0.1+0.2 = 0.30000000000000004,比 0.3 多一丢丢——这能解释不少累加场景是「越加越多」而非「越加越少」。
从某种角度看,屏幕没骗你,是 repr 和 str 的格式化在替你四舍五入。print(0.1+0.2) 给你 0.3,可 0.1+0.2 == 0.3 仍是 False,同一台机器两套说辞。
所以关键大概不在「禁用 double」,而是先想清楚这笔钱会在哪一步被截断、误差往哪儿去。