Python 健壮的numpy.float64相等测试

Python 健壮的numpy.float64相等测试,python,numpy,floating-point,precision,floating-accuracy,Python,Numpy,Floating Point,Precision,Floating Accuracy,是否有一种可靠的方法来测试浮点数的相等性,或者通常确保应该相等的浮点数实际上在浮点数的精度范围内彼此相等?例如,这里有一个令人沮丧的情况: >> 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.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)
,后者更糟


我想知道,有没有更可靠的方法来确定浮点数的相等性,没有误报/误报,没有
a==b
b==a
不同,也不必纠结于公差?如果没有,设置公差以确保稳健行为的最佳实践/建议是什么?

您表示,如果其无限精度形式相等,则希望检查返回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

symphy
库对这种事情有一些支持

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
允许您指定所需的精度(附带一些注意事项)。另外,
sympy
具有
Rational
类。有关详细信息,请参阅

请注意,浮点标准的存在是因为它使用固定位数进行计算。这对处理速度和内存占用都很重要。如果你真的需要这种类型的精确性,特别是如果你在寻找精确的等式,你就应该考虑使用符号求解器(例如Mathematica)。
Python可以做到这一点,但它不是设计用来做到这一点的。

使用epsilon和绝对值:
abs(np.mod(2.1,2)-0.1)<1e-6
?(返回
True
)如果希望精确,请使用整数。否则,您可以将这两个值排序为
isclose
,以便它们是对称的
当它们实际上不应该相等时,它们是相等的
是一个令人费解的短语。你用什么逻辑来决定它们是否应该相等?除了价值之外。派生历史记录?您需要给出
isclose
(或备选方案)不起作用的示例(使您满意)。否则,你将获得否决票和接近票。最明显的例子是
a=1e-8;b=2e-8;np.isclose(a,b)
-->
True
。对此,您可能会说“使用
np.isclose(a,b,atol=1e-9)
-->
False
”,但随后当然是
a=1e-9
b=2e-9
再次返回
True
。另外,正如我已经提到的,
isclose
在文档中不是一个对称关系(我还没有找到一个这样的例子,但这并不意味着它永远不会发生)。我不同意“Python可以做到,但它不是专为做到这一点而设计的”,并表明Python有专门为做到这一点而设计的内置模块。然而,如果你的意思是“NumPy可以做到,但它不是设计用来做到的”,我会同意。它当然有内置的功能可以做到这一点,但我不同意Python是围绕无限/任意精度算法设计的。相比之下,Mathematica是。Mathematica中的数值计算默认支持任意精度。NumPy在游戏中没有皮肤,无论是什么。同意这一点!
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