[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。直到两个向量的元素乘积,它们返回相同的结果。但是,如果我尝试添加它们,它们会变得不同。我相信它与二者的精确设置无关,因为它们都是基于双精度的。为什么会这样?
答案 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因为它总是会产生一个小的舍入错误。无论此错误是向上或向下舍入还是仅从二进制表示中“切断”,都可能出现不同的结果。