检查 Python/numpy 中的 list/array 中是否有特定的浮点值
Checking if a specific float value is in list/array in Python/numpy
检查浮点数之间的相等性时需要小心,并且通常应该考虑到公差,例如使用numpy.allcose.
问题 1: 使用 "in" 关键字检查特定浮点数是否安全(或者是否有类似的 keywords/functions以此目的)?示例:
if myFloatNumber in myListOfFloats:
print('Found it!')
else:
print('Sorry, no luck.')
问题 2:如果不是,什么是整洁的解决方案?
如果您没有在同一个地方或使用完全相同的方程式计算浮点数,那么您可能会使用此代码出现漏报(由于舍入误差)。例如:
>>> 0.1 + 0.2 in [0.6/2, 0.3] # We may want this to be True
False
在这种情况下,我们可以有一个自定义的“in
”函数,它实际上会实现这一点(在这种情况下可能是 better/faster 使用 numpy.isclose
instead of numpy.allclose
):
import numpy as np
def close_to_any(a, floats, **kwargs):
return np.any(np.isclose(a, floats, **kwargs))
文档中有一条重要说明:
Warning
The default atol
is not appropriate for comparing numbers that are much smaller than one (see Notes).
[...]
if the expected values are significantly smaller than one, it can result in false positives.
注释补充说 atol
不为零,这与 math.isclose
的 abs_tol
相反。如果在使用 close_to_any
时需要自定义容差,请使用 kwargs
将 rtol
and/or atol
传递给 numpy。最后,您现有的代码将转换为:
if close_to_any(myFloatNumber, myListOfFloats):
print('Found it!')
else:
print('Sorry, no luck.')
或者您可以有一些选项 close_to_any(myFloatNumber, myListOfFloats, atol=1e-12)
,请注意 1e-12
是任意的,除非您有充分的理由,否则不应使用此值。
回到我们在第一个例子中观察到的舍入误差,这将给出:
>>> close_to_any(0.1 + 0.2, [0.6/2, 0.3])
True
Q1:
取决于您将如何实施。但是正如其他人提到的那样,使用 in
运算符并不是一个好主意。
Q2:
你在性能方面有什么限制吗?
myListOfFloats
会排序吗?
如果它是一个排序的浮点值列表,并且您需要尽可能快地完成它,您可以实施 binary search 算法。
如果数据未排序,根据您将进行的查询数量与数据大小之间的比率,您可能希望对数据进行排序并保持排序。
如果你对性能和速度没有任何要求可以参考下面的例子:
def inrng(number1,number2,prec):
if(abs(number1-number2)<prec):
return True
else:
return False
precision=0.001
for i in myListOfFloats:
if(inrng(i,myInputNumber,precision)):
#do stuff
检查浮点数之间的相等性时需要小心,并且通常应该考虑到公差,例如使用numpy.allcose.
问题 1: 使用 "in" 关键字检查特定浮点数是否安全(或者是否有类似的 keywords/functions以此目的)?示例:
if myFloatNumber in myListOfFloats:
print('Found it!')
else:
print('Sorry, no luck.')
问题 2:如果不是,什么是整洁的解决方案?
如果您没有在同一个地方或使用完全相同的方程式计算浮点数,那么您可能会使用此代码出现漏报(由于舍入误差)。例如:
>>> 0.1 + 0.2 in [0.6/2, 0.3] # We may want this to be True
False
在这种情况下,我们可以有一个自定义的“in
”函数,它实际上会实现这一点(在这种情况下可能是 better/faster 使用 numpy.isclose
instead of numpy.allclose
):
import numpy as np
def close_to_any(a, floats, **kwargs):
return np.any(np.isclose(a, floats, **kwargs))
文档中有一条重要说明:
Warning The default
atol
is not appropriate for comparing numbers that are much smaller than one (see Notes). [...] if the expected values are significantly smaller than one, it can result in false positives.
注释补充说 atol
不为零,这与 math.isclose
的 abs_tol
相反。如果在使用 close_to_any
时需要自定义容差,请使用 kwargs
将 rtol
and/or atol
传递给 numpy。最后,您现有的代码将转换为:
if close_to_any(myFloatNumber, myListOfFloats):
print('Found it!')
else:
print('Sorry, no luck.')
或者您可以有一些选项 close_to_any(myFloatNumber, myListOfFloats, atol=1e-12)
,请注意 1e-12
是任意的,除非您有充分的理由,否则不应使用此值。
回到我们在第一个例子中观察到的舍入误差,这将给出:
>>> close_to_any(0.1 + 0.2, [0.6/2, 0.3])
True
Q1:
取决于您将如何实施。但是正如其他人提到的那样,使用 in
运算符并不是一个好主意。
Q2:
你在性能方面有什么限制吗?
myListOfFloats
会排序吗?
如果它是一个排序的浮点值列表,并且您需要尽可能快地完成它,您可以实施 binary search 算法。
如果数据未排序,根据您将进行的查询数量与数据大小之间的比率,您可能希望对数据进行排序并保持排序。
如果你对性能和速度没有任何要求可以参考下面的例子:
def inrng(number1,number2,prec):
if(abs(number1-number2)<prec):
return True
else:
return False
precision=0.001
for i in myListOfFloats:
if(inrng(i,myInputNumber,precision)):
#do stuff