
那天晚上,我差点以为自己疯了
那天晚上,我写代码写得脑壳有点疼,想偷懒搞点简单的练手题,就随手在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"的小知识,结果越写越上头,写着写着,我都想写本《浮点数的秘密往事》了......
顺手点赞+在看就是对花姐最大的支持❤️! 关注我,带你少踩十年坑,我们下篇见~