Python 2.7浮点数比较异常:0.05==0.05返回False?范围判断遇问题
解决Python 2.7浮点数判断的两个坑
兄弟,你遇到的这俩问题,本质上都是二进制浮点数的精度误差在捣蛋!Python 2.7和绝大多数编程语言一样,采用IEEE 754标准存储浮点数,这种方式没法精确表示所有十进制小数——比如你提到的0.05,转成二进制是无限循环的,所以实际存在内存里的是一个近似值,不是精确的0.05。
第一个问题:0.05 == 0.05返回False?
正常直接写a = 0.05; b = 0.05,a == b肯定是True,但如果其中一个0.05是通过计算得到的(比如0.1 / 2),问题就来了:
a = 0.05 b = 0.1 / 2 print(a == b) # 大概率返回False print(repr(a)) # 输出: 0.05 print(repr(b)) # 输出: 0.05000000000000000277555756156289135105907917022705078125
看到没?repr()会显示浮点数真实的存储值,计算出来的0.05和直接赋值的0.05,其实有极其细微的差异,所以==判断会返回False。
第二个问题:范围判断出现异常
你说的“x和y都等于0.05,但x不被识别”,其实也是同样的道理:假设x是通过运算得到的0.5 + 0.05,它实际存储的是0.5500000000000001,而直接写的0.55存储的是0.5499999999999999。这时候用abs(x - 0.5) <= 0.05判断:
- 对于
0.5499999999999999,差值是0.04999999999999993,小于0.05,会被判定为符合条件; - 对于
0.5500000000000001,差值是0.0500000000000001,大于0.05,就会被排除。
怎么解决这些问题?
给你三个实用方案:
1. 四舍五入后再比较
把浮点数四舍五入到你需要的小数位数(比如两位),再做判断:
# 解决第一个问题 a = 0.05 b = 0.1 / 2 if round(a, 2) == round(b, 2): print("相等") # 会输出 # 解决范围判断问题 x = 0.5 + 0.05 if abs(round(x - 0.5, 2)) <= 0.05: print("在0.5±0.05范围内") # 会输出
2. 用极小的误差阈值(epsilon)替代精确判断
定义一个很小的数值(比如1e-9),判断两个数的差值是否小于这个阈值,而不是直接用==;范围判断时也给阈值留余量:
epsilon = 1e-9 # 相等判断 a = 0.05 b = 0.1 / 2 if abs(a - b) < epsilon: print("相等") # 范围判断 lower = 0.5 - 0.05 upper = 0.5 + 0.05 x = 0.5 + 0.05 if (x >= lower - epsilon) and (x <= upper + epsilon): print("在范围内")
3. 用decimal模块处理精确十进制计算
如果你的场景对精度要求极高(比如货币计算),直接用Python内置的decimal模块,它能精确表示十进制小数:
from decimal import Decimal # 相等判断 a = Decimal('0.05') b = Decimal('0.1') / Decimal('2') print(a == b) # 输出True # 范围判断 target = Decimal('0.5') tolerance = Decimal('0.05') x = Decimal('0.55') if abs(x - target) <= tolerance: print("在0.5±0.05范围内")
内容的提问来源于stack exchange,提问作者Hans




