Numpy减法精度

时间:2017-03-02 19:22:01

标签: python arrays python-3.x numpy

我有一个numpy数组x,它是根据一个复杂的等式计算的:

x = (QT-m_μ_Q*M_T)/(m*σ_Q*Σ_T)
print(x)
print(x[0], x[1], x[2])
print(1.0-x)

打印:

[ 1.  1.  1.]
1.0 1.0 1.0
[ -2.22044605e-16   3.33066907e-16  -4.44089210e-16]

请注意,最后一行打印出一些小而非常接近于零但非零的东西。我的下一步是取每个值的平方根,因此它不应包含负值。

显式地从包含以下内容的数组开始:

y = np.array([1., 1., 1.])
print(y)
print(y[0], y[1], y[2])
print(1.0-y)

产生正确的结果,所以我不确定区别是什么:

[ 1.  1.  1.]
1.0 1.0 1.0
[ 0.  0.  0.]

1 个答案:

答案 0 :(得分:3)

简而言之x中的那些不是真的1.这是因为你操作(你使用的公式)不精确的值(浮动是不精确的,另见Is floating point math broken?)。

但默认精度不会显示差异。但是当你减去一个时,就会得到通常所说的灾难性取消(例如参见WikipediaWhy is 'catastrophic cancellation' called so?)。

例如:

>>> import numpy as np
>>> np.array([1, 1.00000000000002, 1.000000000000002, 1.0000000000000002])
array([ 1.,  1.,  1.,  1.])

>>> 1 - np.array([1, 1.00000000000002, 1.000000000000002, 1.0000000000000002])
array([  0.00000000e+00,  -1.99840144e-14,  -1.99840144e-15, -2.22044605e-16])

通常有两种方法可以解决这个问题:

  • 使用避免灾难性取消的公式(可能无法实现)。但是,在您的情况下,您可以尝试sqrt((y-x)/y)而不是sqrt(1-x/y) - 只需为xQT-m_μ_Q*M_T)和y m*σ_Q*Σ_T插入正确的表达式)。数学上两者都是等价的,但由于浮点数学,这些可能会给出不同的结果。
  • 对结果进行舍入和/或将负值设置为零。