2014-08-30 96 views
0

下面的代码将导致执行打印语句:确定两个复数是否相等

import numpy as np 
import math 

foo = np.array([1/math.sqrt(2), 1/math.sqrt(2)], dtype=np.complex_) 

total = complex(0, 0) 
one = complex(1, 0) 
for f in foo: 
    total = total + pow(np.abs(f), 2) 
    if(total != one): 
     print str(total) + " vs " + str(one) 
     print "NOT EQUAL" 

然而,我的[1/math.sqrt(2), 1/math.sqrt(2)]导致total输入为one

(1+0j) vs (1+0j) NOT EQUAL 

是它将NumPy与Python的复杂类型混合起来有什么用?

+0

尝试'repr(total)'而不是'str(total)' – 2014-08-30 16:25:19

+0

大概这是一个比较浮点数的问题 - 因为复杂类型只是两个浮点数的组合。检查例如这个小指南:http://floating-point-gui.de/errors/comparison/关于如何比较浮点数。同样,试试'2 == sqrt(2)* sqrt(2)'...... – sebastian 2014-08-30 16:25:42

回答

2

我想,同样的考虑实数都适用:永远不要假设他们可以是相等的,而是足够接近:

eps = 0.000001 
if abs(a - b) < eps: 
    print "Equal" 
+3

你也可以使用'np.isclose'或数组'np.allclose' – sebix 2014-08-30 16:55:50

+0

不要*假设*,但有时候可能*知道*。只要你知道哪里会出现错误,浮动平等就不是邪恶的。例如,浮点数就是2 ** 53 IIRC之类的积分。 – Veedrac 2014-08-30 18:49:57

3

当使用浮点数它记住,工作是非常重要的这些数字从来都不准确,因此每次计算都会出现舍入误差。这是由floating point arithmetic的设计引起的,并且是目前在资源有限的计算机上执行高任意精度数学的最实际的方式。你不能使用浮点数精确计算(意味着你实际上没有其他选择),因为你的数字必须在适当的内存空间内切断(大多数情况下最大为64位),这个切断已经完成通过四舍五入(见下面的例子)。

为了正确处理这些缺点,您绝对不应该将它们与平等的花车进行比较,而是为了保持亲密。 Numpy为此提供了2个函数:np.isclose用于比较单个值(或数组的项目式比较)和整个数组的np.allclose。后者是np.all(np.isclose(a, b)),所以你得到一个数组的单个值。

>>> np.isclose(np.float32('1.000001'), np.float32('0.999999')) 
True 

但有时四舍五入是非常可行并与我们的analytical预期相符,例如参见:

>>> np.float(1) == np.square(np.sqrt(1)) 
True 

平方值后的尺寸将被缩小到适合在给定的内存,所以在这种情况是四舍五入到我们所期望的。

这两个函数具有内置的绝对和相对公差(您也可以将其作为参数)用于比较两个值。默认情况下,它们是rtol=1e-05atol=1e-08


此外,不要混合不同的包与他们的类型。如果您使用Numpy,请使用Numpy-Types和Numpy-Functions。这也会减少舍入误差。

顺便说一句:在使用广泛指数不同的数字时,舍入误差会产生更大的影响。

+0

正如我回答贝雷尔,重要的是要注意浮点*数字*是确切的;它仅仅是*一些*浮点操作*不是。例如,'16.0 ** 0.5'总是会给出'4.0'的确切答案,但是像'10 ** 0.5'这样的东西显然必须四舍五入。通常(但不总是),如果输入和输出完全可表示,则计算将是精确的。 – Veedrac 2014-08-30 18:54:34

+0

是的,谢谢。数字总是精确的,操作必须将数字四舍五入,因此不准确。我在我的回答中澄清了这一点。 – sebix 2014-08-30 19:30:50

+0

@Veedrac Well'10 ** 0.5'由于数字不合理而显得很明显。据我所知,这不仅关乎精度,还关系到十进制和二进制系统之间的根本差距,因为像'0.1'这样的数字不能有有限的二进制表示,与'1/3'相同没有有限的小数表示。出于这个原因,例如,'1.1 + 2.2 == 3.3'结果是'False',即使操作是微不足道的,指数也是一样的。 – bereal 2014-08-31 06:53:07