健壮的 numpy.float64 平等测试

robust numpy.float64 equality testing

是否有可靠的方法来测试浮点数是否相等,或者通常确保应该相等的浮点数实际上在浮点数的精度范围内彼此相等?例如,这是一个令人苦恼的情况:

>> np.mod(2.1, 2) == 0.1
Out[96]: False

我意识到这是由于浮点错误引起的:

>> np.mod(2.1, 2)
Out[98]: 0.10000000000000009

我熟悉 np.isclose(a,b,tol) 函数,但使用它让我感到不舒服,因为我可能会得到误报,即被告知事情是平等的,而实际上它们不应该是平等的。还有一个注意事项 np.isclose(a,b) 可能与 np.isclose(b,a) 不同,后者更糟。

我想知道,是否有更稳健的方法来确定浮点数的相等性,没有错误的 positives/false 负数,没有 a==bb==a 不同并且不必乱七八糟公差?如果不是,什么是最好的 practices/recommendations 来设置公差以确保稳健的行为?

您声明如果它们的无限精度形式相等,您希望检查 return True。在那种情况下,您需要使用无限精度的数据结构。例如 fractions.Fraction:

>>> from fractions import Fraction
>>> Fraction(21, 10) % 2 == Fraction(1, 10)
True

还有(虽然很慢!)支持包含 python 个对象的数组:

>>> import numpy as np
>>> arr = np.array([Fraction(1, 10), Fraction(11, 10), Fraction(21, 10), 
...                 Fraction(31, 10), Fraction(41, 10)])
>>> arr % 2 == Fraction(1, 10)
array([ True, False,  True, False,  True], dtype=bool)

您只需确保不会丢失无限精度的对象(这对于几个 numpy/scipy 函数来说并不容易)。

在你的情况下,你甚至可以只对整数进行操作:

>>> 21 % 20 == 1
True

sympy 库对这种东西有一些支持。

from sympy import *

a, b = GoldenRatio**1000/sqrt(5), fibonacci(1000)
print(float(a))
# prints 4.34665576869e+208
print(float(b))
# prints 4.34665576869e+208
print("Floats: ", float(a) - float(b))
# prints 0.0
print("More precise: ", N(fibonacci(100) - GoldenRatio**100/sqrt(5)))
# prints -5.64613129282185e-22

N 允许您指定您想要的精度(有一些注意事项)。此外,sympyRational class。有关详细信息,请参阅 here

请注意,存在浮点标准是因为它使用固定位数进行计算。这对于处理速度和内存占用都很重要。如果您确实需要这种类型的精度,特别是如果您正在寻找精确的相等性,那么您真的应该考虑使用符号求解器(例如 Mathematica)。

Python 可以做到,但设计 并非如此。