Python和R返回不同的结果,它们应该完全相同

时间:2016-09-11 08:39:27

标签: python r numpy

[Python numpy code]

In [171]: A1*b
Out[171]: 
array([ -7.55603523e-01,   7.18519356e-01,   3.98628050e-03,
     9.27047917e-04,  -1.31074698e-03,   1.44455190e-03,
     1.02676602e-03,   5.03891225e-02,  -1.15752426e-03,
    -2.43685270e-02,   5.88382307e-03,   2.63372861e-04])
In [172]: (A1*b).sum()
Out[172]: -1.6702134467139196e-16    

[R代码]

> cholcholT[2,] * b
[1] -0.7556035225  0.7185193560  0.0039862805  0.0009270479 -0.0013107470
[6]  0.0014445519  0.0010267660  0.0503891225 -0.0011575243 -0.0243685270
[11]  0.0058838231  0.0002633729
> sum(cholcholT[2,] * b)
[1] -9.616873e-17

第一个是R代码,第二个是numpy。直到两个向量的元素乘积,它们返回相同的结果。但是,如果我尝试添加它们,它们会变得不同。我相信它与二者的精确设置无关,因为它们都是基于双精度的。为什么会这样?

2 个答案:

答案 0 :(得分:2)

您正在体验所谓的灾难性取消。您正在减去彼此之间的数字,这些数字之间的差异非常小。结果,您得到的数字相对于它们的值具有非常高的误差。该错误源于舍入错误,这些错误是在系统存储无法准确表示二进制系统的值时引入的。

直观地说,您可以将此视为将1/3作为十进制数写入时遇到的相同困难。你必须写0.3333 ...,所以小数点后面的无限多3s。你不能这样做,你的电脑也不能。

因此,您的计算机必须将数字四舍五入。

如果您使用

之类的内容,则可以看到舍入错误
"{:.20e}".format(0.1)

您将看到在第16位左右之后您要存储的数字(1.0000000000000000000 ...×10 ^ -1)与计算机存储的数字不同(1.00000000000000005551 ...×10 ^ -1)< / p>

要查看此不准确性的数量级,您可以查看 machine epsilon 。简单来说,此值为您提供了相对于您可以添加到值的值的最小量,以便计算机仍然可以将结果与旧值区分开来(因此在将结果存储在内存中时不会将其舍入)。

如果你执行

import numpy as np
eps = np.finfo(float).eps

你可以看到这个值位于10 ^ -16的数量级。

计算机以SIGN|EXPONENT|FRACTION之类的形式表示浮动。因此,为了大大简化,如果计算机内存将以十进制格式存储数字,则将类似-0.0053的数字存储为1|-2|.53|1代表负号,-2表示'分数乘以10 ^ -2'。

如果总结浮点数,计算机必须用相同的指数表示每个浮点数,以相互加/减数字形式的数字。因此,所有值都将以数据的最大指数表示,即-1。因此,您的舍入误差将在10 ^ -16 * 10 ^ -1的数量级,即10 ^ -17。你可以看到你的结果也是这个数量级的,所以它很大程度上受到数字舍入误差的影响。

答案 1 :(得分:1)

您正在使用浮点数并对其应用算术运算。 Floating point arithmetic is a dangerous thing因为它总是会产生一个小的舍入错误。无论此错误是向上或向下舍入还是仅从二进制表示中“切断”,都可能出现不同的结果。