我想到比较浮点数的一个好方法是用浮点数缩放容差。这是个好主意吗?
这个例程需要针对特殊量进行扩展,例如 NaN、+/-Inf,但它给出了一个基本的想法。
def FloatEq(a, b, ToleranceFactor=1e-6):
if a == b: return True
c = min(abs(a), abs(b))
return(abs(a-b) < (c*ToleranceFactor))
a = 0.000000000001
b = 0.000000000001000000001
print('Straight compare ==', a==b)
print('FloatEq(,,1e-6) ==', FloatEq(a,b))
print('FloatEq(,,1e-10) ==', FloatEq(a,b,1e-10))
输出:
Straight compare == False
FloatEq(,,1e-6) == True
FloatEq(,,1e-10) == False
更新:
一种可能的解决方案可以处理操作数之一为零的情况。它使用固定的、用户可配置的容差,而不是因子。
def FloatEq(a, b, ToleranceFactor=1e-6, ToleranceAtZero=None):
if a == b:
return True
elif a==0 or b==0:
c = a if b==0 else b
if ToleranceAtZero is None:
import sys
# Ignoring denormalized numbers for now
ToleranceAtZero = sys.float_info.min
return abs(c) < ToleranceAtZero
else:
c = min(abs(a), abs(b))
return(abs(a-b) < (c*ToleranceFactor))
这是一个明智的想法,除非您要比较可能是“灾难性取消”结果的值(例如,减去两个附近的数字以产生一个非常小、非常不准确的数字。)在这种情况下,我认为您应该缩放您对取消前值大小的容忍度。
我不是数值计算/浮点专家。把这些东西做好是很困难的,并且有一个完整的堆栈交换:Computational Science.SE。
出现了一些搜索:https://scicomp.stackexchange.com/questions/3362/relative-comparison-of-floating-point-numbers有几个关于 FP 比较的答案。