You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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.05a == 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

火山引擎 最新活动