Python中接近1的浮点数取无穷大幂的阈值及精度提升问题
Python中接近1的浮点数取无穷大幂的阈值及精度提升问题
咱们先从你观察到的现象说起,这个差异确实挺有意思的:
1.000000000000001 ** float('inf') == float('inf') # 结果为True而
1.0000000000000001 ** float('inf') == 1.0 # 结果为True
为什么会有这个阈值?
这本质是Python默认的float类型(64位双精度浮点数)的精度限制导致的。双精度浮点数的尾数部分有52位二进制位,这决定了1.0和下一个能被精确表示的双精度浮点数之间的差值是2^-52(约等于2.220446049250313e-16),这个值也叫「机器epsilon」。
- 当你写
1.0000000000000001时,它和1.0的差值是1e-16,比2^-52要小——双精度浮点数没法区分这么小的差异,会直接把这个数舍入成1.0。那1.0的无穷大次幂自然还是1.0。 - 而
1.000000000000001和1.0的差值是1e-15,比2^-52大,所以它能被正确表示成一个严格大于1.0的浮点数。按照数学规则,任何严格大于1的数的无穷大次幂都是无穷大,所以结果就是float('inf')。
简单说,这个阈值就是双精度浮点数的机器epsilon:只要数和1.0的差值小于它,就会被当成1.0处理;大于等于的话,就会被识别为大于1的数。
怎么提升精度避免这个问题?
如果你需要精确处理这种接近1的小数,有两个实用的办法:
- 用
decimal模块自定义精度
这个模块可以让你手动设置小数的精度,完全避开双精度的限制。比如:
from decimal import Decimal, getcontext # 把精度设置到足够高,比如30位,能覆盖你需要的小数位数 getcontext().prec = 30 num1 = Decimal('1.0000000000000001') num2 = Decimal('1.000000000000001') inf = Decimal('Infinity') print(num1 ** inf) # 输出1 print(num2 ** inf) # 输出Infinity
这样就能精准区分这两个数,得到符合预期的计算结果。
- 用
fractions模块做精确分数运算
如果你的数可以表示成整数的分数形式,用分数类型能彻底避免浮点数的舍入误差:
from fractions import Fraction # 把两个小数转成分数形式 num1 = Fraction(10000000000000001, 10000000000000000) num2 = Fraction(100000000000001, 100000000000000) inf = float('inf') print(float(num1 ** inf)) # 输出1.0 print(float(num2 ** inf)) # 输出inf
这种方式基于精确的整数运算,完全不会有精度丢失的问题。
备注:内容来源于stack exchange,提问作者Elan SK
相关产品推荐
相关产品推荐

