网易首页 > 网易号 > 正文 申请入驻

Python把0.1+0.2算错这事

0
分享至


0.1加0.2等于多少?

如果你的第一反应是0.3,恭喜你,你和Python一样天真。在Python解释器里敲下这行代码,返回的是0.30000000000000004——一个比正确答案多出0.00000000000000004的怪物。这个误差小到肉眼看不见,却大到能让一家年处理36亿笔交易的金融科技公司,每年凭空蒸发1900万美元。

01 | 十亿美金的bug:PhonePe的浮点陷阱

印度支付巨头PhonePe每天处理约1亿笔交易。假设每笔收取0.1美元手续费,用标准Python浮点数累加,一天下来账面会少收0.19美元。一年就是69美元,十年690美元——听起来像 rounding error(舍入误差)的教科书案例,对吧?

但真实的金融系统从不只做一次加法。同一笔资金要在清算系统、风控系统、报表系统、审计系统里流转数十次。每次浮点运算都引入新的噪声,误差像滚雪球一样膨胀。原文给出的模拟结果显示:单次批次1000万笔交易就损失0.19美元,而PhonePe的实际规模是模拟数据的10倍。按原文的警告,"This scales into thousands quickly over years"——几年内累积到数千美元只是起点,跨国支付网络的复合误差足以让CFO在年报里看到幽灵亏损。

更隐蔽的是追查成本。当审计发现账目对不上,团队要花费数百人时定位问题。浮点误差没有日志、没有堆栈追踪,它安静地潜伏在十进制与二进制的夹缝中,等你发现时已经污染了整个数据管道。

02 | 硬件原罪:为什么CPU天生不会算0.1

人类用十进制思考,计算机用二进制生存。这个错位是浮点误差的根源,不是Python的锅。

我们用10的幂次构建分数:1/10、1/100、1/1000。0.1在十进制里是干净的有限小数。但CPU的物理电路只认识0和1,它必须用2的幂次逼近这个数:1/2、1/4、1/8、1/16……

数学上,1/10无法表示为有限个1/2^n的和。就像你永远无法用1/3英寸的砖块精确铺满1英尺的长度,CPU也永远无法用二进制位精确存储0.1。它只能写下0.00011001100110011……然后被迫截断。

IEEE 754标准给了64位存储空间。0.1被编码后,实际存入内存的是0.100000000000000005551115123125——一个比真实值多出5.55×10^-18的冒牌货。单次运算的偏差小于尘埃,但数十亿次累加后,尘埃变成沙丘。

原文把这个困境称为"The CPU's Dilemma"(CPU的困境)。这不是设计缺陷,是物理定律的硬边界。所有主流语言——JavaScript、C++、Java、Ruby——共享同一块硅片的诅咒。Python只是诚实地暴露了问题,而不是制造问题。

03 | Decimal模块:用软件对抗硬件

Python的解决方案是decimal模块。它不碰CPU的浮点运算单元(FPU),完全在软件层模拟十进制算术。代价是速度——比原生float慢10到100倍——换来的是金融级精度。

使用方法很直白:

```python
from decimal import Decimal, getcontext
getcontext().prec = 28 # 设置全局精度
fee = Decimal('0.10') # 注意用字符串初始化
total = sum([fee] * 100_000_000)
print(total) # 精确输出 10000000.00
```

关键细节是字符串初始化。写成Decimal(0.1)会先让Python用float解析0.1,再把已经污染的数值传给Decimal,等于先喝毒药再求医。Decimal('0.1')才是正确的打开方式,它绕过硬件浮点,直接从字符序列重建十进制语义。

精度控制是另一道防线。getcontext().prec默认28位有效数字,足以覆盖地球上所有流通货币的最小单位。处理纳米级科学计算时可以上调,日常财务场景保持默认即可。

原文把float用于金钱称为"architectural sin"(架构层面的原罪)。这个措辞很重,但合理——因为错误发生在设计阶段,而不是编码阶段。等到生产环境出现0.19美元的缺口,再迁移到Decimal的成本是重写核心账务模块。

04 | Statistics模块:当平均值撒谎

精度问题不止于加减乘除。Python的statistics模块处理的是另一类陷阱:统计量本身的数值稳定性。

计算方差的标准算法是先求均值,再对每个数据点做平方差累加。这个两趟算法在数学上正确,在计算机里危险。当数据集的数值很大但方差很小时,平方差会淹没在浮点舍入噪声中。

statistics.variance()内部实现了Welford在线算法,单趟扫描即可输出结果,且数值稳定性优于教科书公式。对于普通开发者,这意味着:

```python
# 危险:手动实现
def naive_variance(data):
n = len(data)
mean = sum(data) / n
return sum((x - mean) ** 2 for x in data) / (n - 1)
# 安全:调用标准库
from statistics import variance
variance(data) # 自动选择最优算法
```

原文没有展开statistics模块的细节,但提到了一个关键原则:数学上的等价不等于计算上的等价。两个公式在实数域给出相同结果,在浮点数域可能相差数个数量级。标准库的价值在于隐藏这些陷阱,让开发者不必成为数值分析专家。

05 | IEEE 754的边界:无穷、NaN与静默失败

浮点数系统不只有精度问题。IEEE 754标准定义了三个特殊值:正无穷(inf)、负无穷(-inf)、非数(NaN,Not a Number)。它们是错误处理的备用通道,也是静默灾难的温床。

除以零在Python里不抛异常,而是返回inf:

```python
>>> 1.0 / 0.0
inf
>>> -1.0 / 0.0
-inf
>>> 0.0 / 0.0
nan
```

这个设计有利有弊。科学计算中,inf可以参与后续运算(比如无穷大乘以零得到NaN),保持流水线不中断。但业务代码里,一个未检查的inf可能穿透十层函数调用,最终在报表里变成"Infinity"字符串,或者更糟——被强制转换为某个巨大的整数。

NaN的传播性更隐蔽。任何涉及NaN的运算都返回NaN,且NaN不等于任何值,包括它自己:

```python
>>> nan = float('nan')
>>> nan == nan
False
>>> nan in [nan]
True # 列表成员检查用is,不是==
```

这意味着简单的相等判断无法检测NaN污染。必须用math.isnan()显式检查,或者让pandas/numpy的严格模式替你拦截。

原文的警告很直接:"your data will slowly, silently corrupt itself"(你的数据会缓慢、无声地自我腐化)。IEEE 754的特殊值机制是这种腐化的主要载体。它们让程序"看起来正常",直到某个下游环节崩溃。

06 | 架构师的决策树:什么时候用什么

不是所有场景都需要Decimal的精度。原生float在科学计算、图形渲染、机器学习领域仍是首选,因为速度差距无法忽视。关键是在架构层面划定边界:

必须用Decimal的场景:货币金额、税率、汇率、账户余额、任何需要精确到最小货币单位的数值。判断标准是:如果误差会导致法律纠纷或审计失败,就用Decimal。

可以用float的场景:物理模拟、信号处理、统计抽样、任何容忍相对误差<0.1%的领域。判断标准是:误差可以被"足够好"的近似覆盖。

必须显式检查的场景:用户输入、外部API返回、数据库读取的浮点字段。任何穿越系统边界的数值都可能是NaN或inf的特洛伊木马。

原文的立场很明确:"Code is just syntax. Mathematics is the universal law governing that syntax."(代码只是语法,数学是支配语法的普遍法则。)Junior开发者相信语法正确即结果正确,Senior架构师知道物理硬件的约束才是真正的边界条件。

PhonePe的案例不是虚构。2023年印度UPI网络处理超过120亿笔交易,任何头部玩家的系统架构都必须面对这个选择:为每笔交易多消耗10微秒的CPU时间,还是承担每年数千万美元的隐性损失。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
震惊!裸车仅4.3万的张雪820机车,上海落地要53万,差价近乎十倍

震惊!裸车仅4.3万的张雪820机车,上海落地要53万,差价近乎十倍

火山詩话
2026-04-05 08:07:32
0-4惨败,中国女足获得蒙太古杯亚军,连续2届决赛输给日本

0-4惨败,中国女足获得蒙太古杯亚军,连续2届决赛输给日本

侧身凌空斩
2026-04-06 04:59:02
天啦!有传川普挂了?!

天啦!有传川普挂了?!

不与世俗同
2026-04-05 21:59:14
周鸿祎被牙哥嘲笑:傻乎乎、喷口水,投资哪吒19亿花5亿设计logo

周鸿祎被牙哥嘲笑:傻乎乎、喷口水,投资哪吒19亿花5亿设计logo

江山挥笔
2026-04-06 09:53:35
国务院825号令来了!这9种执法不准再做,老百姓遇事先留3样证据

国务院825号令来了!这9种执法不准再做,老百姓遇事先留3样证据

花小猫的美食日常
2026-04-06 08:24:10
伊朗的这次轰炸太狠了,直接断了美国的命根子!

伊朗的这次轰炸太狠了,直接断了美国的命根子!

华人星光
2026-04-05 11:38:43
曝字母哥被交易几成定局!今夏听取各队报价:四大方案谁更诱人?

曝字母哥被交易几成定局!今夏听取各队报价:四大方案谁更诱人?

罗说NBA
2026-04-05 22:14:37
永州一车辆侧翻致3死2伤,村民称事发地山路陡峭,当地政府工作人员:扫墓途中小轿车发生意外

永州一车辆侧翻致3死2伤,村民称事发地山路陡峭,当地政府工作人员:扫墓途中小轿车发生意外

极目新闻
2026-04-06 00:19:40
李泽楷被她迷得疯狂,林丹为她不顾孕妻,她有什么魅力?

李泽楷被她迷得疯狂,林丹为她不顾孕妻,她有什么魅力?

观察鉴娱
2026-04-05 21:26:05
突袭伊朗核电站!第四次爆炸震动全球,以色列这次玩大了?

突袭伊朗核电站!第四次爆炸震动全球,以色列这次玩大了?

菁菁子衿
2026-04-06 11:01:44
独木难支,詹姆斯22投12中砍30+9+15准三双,正负值+1

独木难支,詹姆斯22投12中砍30+9+15准三双,正负值+1

懂球帝
2026-04-06 11:07:14
超大单!英伟达220万张、华为81.2万张、阿里26.5万张

超大单!英伟达220万张、华为81.2万张、阿里26.5万张

最通信
2026-04-05 20:57:07
“馆长”质问民进党:不是中国人?那过啥清明节?

“馆长”质问民进党:不是中国人?那过啥清明节?

看看新闻Knews
2026-04-05 18:23:12
伊朗越打越猛!美媒问了中国一个敏感问题,毛宁的回答水平很高

伊朗越打越猛!美媒问了中国一个敏感问题,毛宁的回答水平很高

人生录
2026-04-05 12:35:37
近12战10胜!双探花49+19绿军横扫猛龙 武切维奇时隔30天复出

近12战10胜!双探花49+19绿军横扫猛龙 武切维奇时隔30天复出

醉卧浮生
2026-04-06 05:51:20
毛主席唯一一个活下来的儿子毛岸青,晚年的时候享受的什么待遇?

毛主席唯一一个活下来的儿子毛岸青,晚年的时候享受的什么待遇?

乐天闲聊
2026-02-13 11:33:46
70岁米歇尔求婚小他17岁的巩俐:我年入5亿,嫁给我!巩俐:我每周做4次有氧运动,你行吗?

70岁米歇尔求婚小他17岁的巩俐:我年入5亿,嫁给我!巩俐:我每周做4次有氧运动,你行吗?

乔话
2026-04-04 19:18:16
崩得最彻底的专业,连985毕业生都哭诉:越努力越不幸!

崩得最彻底的专业,连985毕业生都哭诉:越努力越不幸!

黯泉
2026-04-05 20:49:28
保密期限终到期,中央首长透露:毛岸英真相,可以向外界公开了

保密期限终到期,中央首长透露:毛岸英真相,可以向外界公开了

历史点行
2026-03-29 13:38:28
尘埃落定…… 齐达内多年等待,终于圆梦!执掌法国国家队

尘埃落定…… 齐达内多年等待,终于圆梦!执掌法国国家队

夜白侃球
2026-04-05 21:50:34
2026-04-06 11:40:49
算力游侠
算力游侠
游走在API与报错之间,用魔法(AI)打败魔法的非硬核玩家。
797文章数 8关注度
往期回顾 全部

科技要闻

前同事被蒸馏成Token,AI能否偷走职场经验

头条要闻

媒体:美军拯救大兵有奇怪之处 未展示飞行员获救照片

头条要闻

媒体:美军拯救大兵有奇怪之处 未展示飞行员获救照片

体育要闻

CBA最老球员,身价7500万美元

娱乐要闻

乔任梁离世10年 父母曝舞台光鲜的背后

财经要闻

118吨!这家央行,大幅抛售黄金!

汽车要闻

家用SUV没驾驶乐趣?极氪8X第一个不同意

态度原创

游戏
房产
旅游
手机
军事航空

Xbox大作稳了!《腐烂国度3》内部测试好玩到爆炸

房产要闻

小阳春全面启动!现房,才是这波行情里最稳的上车票

旅游要闻

露营经济升温 威海户外装备市场火热

手机要闻

vivo X300s / X300 Ultra维修备件价格公布,199换电池

军事要闻

美飞行员获救细节:美伊发生激烈交火 至少4死1伤

无障碍浏览 进入关怀版