【问题标题】:Checking if a specific float value is in list/array in Python/numpy检查特定的浮点值是否在 Python/numpy 的列表/数组中
【发布时间】:2019-08-09 20:47:19
【问题描述】:

在检查浮点数之间的相等性时需要小心,并且通常应该考虑到容差,例如使用numpy.allcose.

问题 1: 使用“in”关键字检查特定浮点数的出现是否安全(或者是否有类似的关键字/函数用于此目的)?示例:

if myFloatNumber in myListOfFloats:
  print('Found it!')
else:
  print('Sorry, no luck.')

问题 2:如果不是,那么整洁的解决方案是什么?

【问题讨论】:

  • 是的,为什么你会觉得它不好?
  • 我认为如果您使用与myListOfFloats 的元素不同的公式计算myFloatNumber,则此评论是有效的。如果你用完全相同的代码得到这些数字,那么所有的错误都是一样的,你不会有任何问题。
  • 或者样本 I/O 可以做到这一点
  • 是的,你必须小心这个,例如3.4 in [3.45, 5] -> False。一种选择是使用decimal 模块将列表中的所有浮点数剪切到相关浮点数的长度,然后检查它是否在列表中
  • 整洁的解决方案:np.isclose(<your_array>, <your_ref_value>).any()。如果需要,您可以将公差传递给isclose

标签: python numpy floating-point floating-point-comparison


【解决方案1】:

如果您不在同一个地方或使用完全相同的方程式计算您的浮点数,那么您可能会对这段代码产生误报(因为舍入错误)。例如:

>>> 0.1 + 0.2 in [0.6/2, 0.3]  # We may want this to be True
False

在这种情况下,我们可以只使用一个自定义的“in”函数来实现这一点(在这种情况下,使用numpy.isclose 而不是numpy.allclose 可能会更好/更快):

import numpy as np 

def close_to_any(a, floats, **kwargs):
  return np.any(np.isclose(a, floats, **kwargs))

文档中有一个重要说明:

警告 默认atol 不适用于比较远小于一的数字(请参阅注释)。 [...] 如果期望值明显小于 1,则可能导致误报。

注释补充说,atol 不是零,与 math.iscloseabs_tol 相反。如果您在使用close_to_any 时需要自定义容差,请使用kwargsrtol 和/或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

【讨论】:

  • 感谢您提供的代码示例。我想知道为什么已经没有官方的关键字/numpy函数了……
  • 我认为存在这样的功能是有意义的,但另一方面,如果您查看我的编辑,这基本上是np.allcloseany 的组合。我试图在文档中找到它,但我认为它不存在。
【解决方案2】:

第一季度: 取决于你将如何实现这一点。但正如其他人提到的那样,使用 in 运算符并不是一个好主意。

第二季度: 您在性能方面有任何限制吗? 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

【讨论】:

    猜你喜欢
    • 2020-03-15
    • 2019-06-27
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 2013-12-26
    • 2020-07-05
    相关资源
    最近更新 更多