出大事了!0.1 + 0.2 居然不等于 0.3,Python我再也不敢用了…

那天晚上,我差点以为自己疯了

那天晚上,我写代码写得脑壳有点疼,想偷懒搞点简单的练手题,就随手在Python里敲了一句:

python 复制代码
print(0.1 + 0.2 == 0.3)

本来想着随便跑一下,顺便热热键盘。

结果------False???

我一瞬间怀疑人生:我小学数学白学了吗??0.1 + 0.2 还能不等于 0.3?

我愣住了几秒,脑子一边在拼命回忆《十万个为什么》,一边在疯狂怀疑是不是键盘出问题了。


这不是bug,这是浮点数的"老毛病"💣

如果你以前没遇到过这个问题,别慌,其实不是 Python 坏掉了,而是所有编程语言(几乎)都有这个毛病,根源在于:

💡 浮点数在计算机中没法完美表示,尤其是像 0.1、0.2 这种"小数点后看着很乖"的家伙。

来,我举个简单例子,展示一下到底发生了什么:

python 复制代码
print(0.1 + 0.2)  # 输出:0.30000000000000004

对,你没看错,0.1 + 0.2 实际结果是 0.30000000000000004

想象一下:

你在某宝下单买两样小商品,一个 0.1 元、一个 0.2 元,按理说总价 0.3 元对吧?结果系统后台一算,说你这笔订单金额不合法,直接拦住了。你一脸懵,客服也搞不清楚,最后发现居然是浮点数精度在搞鬼。

听起来很荒谬,但真相就是这么魔幻。


真相大白:0.1 是个"在二进制里没法好好存"的数字

我们得稍微来点底层知识,不难理解:

0.1、0.2 这些十进制小数,其实在 二进制里是无限循环小数,就像十进制里 1/3 是 0.33333...

计算机又不能真存"无限多位",只能找个差不多的近似值存起来。

于是就出事了:

你以为你存的是 0.1,实际上你存的是个近似值,大概长这样:

python 复制代码
0.1 实际是:0.10000000000000000555...
0.2 实际是:0.20000000000000001110...
加起来就变成了:0.3000000000000000444...

那你再拿这玩意和"你心目中正儿八经的0.3"一比:

python 复制代码
0.3 实际是:0.29999999999999998889...

嘿嘿,差了几微粒,Python 一看,嗯你俩不一样,直接给你判 False。


那为啥 1.1 + 1.2 == 2.3 就没问题?

这个就很有趣了。

python 复制代码
print(1.1 + 1.2 == 2.3)  # True

很多人看到这段会更困惑:这不双标嘛?

其实不是双标,是因为 1.1 + 1.2 的浮点误差比较小,结果正好和 2.3 的误差差不多方向,Python 一看俩都歪一点,但歪得方向一致,那就算你俩对得上。

你可以理解为:

它们都走偏了,但刚好走偏的路数对上了,大家都往右边歪了一点,于是"装模作样"地对上号了。


真正致命的是:这误差可能影响你的业务逻辑!💥

比如你在做支付判断:

python 复制代码
price = 0.1 + 0.2
if price == 0.3:
    print("支付成功!")
else:
    print("金额异常,支付失败!")

你以为你写得挺靠谱,结果用户一付款,系统说金额对不上?

一脸懵逼的客服+崩溃的开发+火冒三丈的用户 = 灾难现场。


那到底哪些数字容易出问题?我该怎么防?

说到底,咱们想知道的无非就是:

👉 哪些数字得小心?

👉 哪些场景最容易翻车?

👉 怎么避免这个坑?

别急,花姐给你梳理一张清单:

哪些数字是"雷区"?🔥

数字类型 是否安全
0.1、0.2、0.3 ❌ 极容易出问题
0.5、0.25、0.75 ✅ 安全(2 的幂次组合)
整数 ✅ 完美无瑕
连续累加浮点数 ❌ 极易误差累积

如果你还是一脸懵逼,不妨把他们改成二进制试试 举例说明一下👇

十进制 二进制表示 是否安全
0.5 0.1
0.25 0.01
0.75 0.11
0.1 0.0001100110011...(无限循环)

你容易翻车的实际场景:

场景 风险点 推荐方案
电商金额判断 误差导致金额不符 用 Decimal
金融计算(利息、年化收益) 误差积累 Decimal + round
科学计算归一化 误差放大结果偏离 用 numpy + isclose
游戏角色坐标 坐标抖动错位 尽量用整数坐标

正确姿势来了✅

1. 用 Decimal 精准搞定金额:

python 复制代码
from decimal import Decimal

a = Decimal('0.1')
b = Decimal('0.2')
c = Decimal('0.3')

print(a + b == c)  # True

字符串传入,完全避免浮点存储误差。


2. 判断浮点是否"足够接近":math.isclose

python 复制代码
import math

print(math.isclose(0.1 + 0.2, 0.3))  # True

这个判断方式才是靠谱的 float 比较方式!


3. 千万别这样比!

python 复制代码
if a + b == 0.3:  # ❌ 一定不要这么比

最后说一句

说到底,浮点数的锅,不是Python独有的锅,Java、C++、JavaScript 甚至 Excel 都中这个招。

你不能不信它,但也不能完全信它。

当我们知道它的脾气,就能少踩很多坑。


结尾

就像我写这篇文章的时候,原本只是想分享个"0.1+0.2 != 0.3"的小知识,结果越写越上头,写着写着,我都想写本《浮点数的秘密往事》了......

顺手点赞+在看就是对花姐最大的支持❤️! 关注我,带你少踩十年坑,我们下篇见~

相关推荐
左灯右行的爱情1 分钟前
缓存并发更新的挑战
jvm·数据库·redis·后端·缓存
brzhang5 分钟前
告别『上线裸奔』!一文带你配齐生产级 Web 应用的 10 大核心组件
前端·后端·架构
shepherd1116 分钟前
Kafka生产环境实战经验深度总结,让你少走弯路
后端·面试·kafka
袋鱼不重19 分钟前
Cursor 最简易上手体验:谷歌浏览器插件开发3s搞定!
前端·后端·cursor
嘻嘻哈哈开森21 分钟前
Agent 系统技术分享
后端
用户40993225021222 分钟前
异步IO与Tortoise-ORM的数据库
后端·ai编程·trae
大模型真好玩26 分钟前
初学者必看大模型微调指南:Unsloth官方微调技巧大公开!
人工智能·python
会有猫27 分钟前
LabelStudio使用阿里云OSS教程
后端
惜鸟27 分钟前
如何从模型返回结构化数据
后端
GZ25332 分钟前
Smart Input Pro使用教程
后端