【问题标题】:Difference in sum of an array using python and matlab code使用python和matlab代码的数组总和的差异
【发布时间】:2014-07-14 05:42:02
【问题描述】:

Here 是我想要总和的 mat 文件 temp 的链接。 python 的总和是 1.1230325644146074e-10。 matlab 中的总和为 1.2189e-010。但是当我从 matlab 复制数组并将它们添加到 python 终端时,我得到与 matlab 相同的总和。这背后的奥秘是什么?

>>> np.sum(temp) 

1.1230325644146074e-10

>>> 0 + 1.34369215036371e-13 + 1.44714547828739e-11 + 3.13077747300113e-11 + 0 +         
    7.33156408714693e-10 + 1.07579271945635e-08 + 8.89446393156299e-09 + 0 + 
    8.00303861023109e-08 + 9.10095259764947e-07 + 6.44662571715407e-07 + 0 + 
    6.16697002187199e-06 + 0.000104686113649727 + 0.000240373037717048 + 
    7.07802623602744e-11 + -0.000240372993389479 + -0.000104686106424492 + 
    -6.16697038783319e-06 + 0 + -6.44662640770614e-07 + -9.10095265552302e-07 + 
    -8.00303919930304e-08 + 0 + -8.89446408625544e-09 + -1.07579272042352e-08 +   
    -7.33156409297323e-10 + 0 + -3.13077747365376e-11 + -1.44714547888711e-11 + 
    -1.34369215245131e-13

1.218862069269912e-10

所有这些都是必需的,因为下面代码中的 num 是从 temp 派生的,然后我有一个 den 或分母组件,我试图找到除法。因此,即使这些值很小但存在小错误,当我将 matlab 代码转换为 python 时,它们的划分也会产生错误。

这是matlab代码。

function mth = compute_mean_angle(dEnergy,th)
global NFFT;
sth         =   sin(2*th);
cth         =   cos(2*th);
num         =   sum(sum(dEnergy.*sth));
den         =   sum(sum(dEnergy.*cth));
mth         =   0.5*atan2(num,den);
if(mth <0)
    mth = mth+pi;
end;

%end function compute_mean_angle

这里是python代码。

def compute_mean_angle(dEnergy, th):
    global NFFT
    sth = np.sin(np.dot(2, th))
    cth = np.cos(np.dot(2, th))
    num = np.sum(np.sum(dEnergy * sth))
    den = np.sum(np.sum(dEnergy * cth))
    mth = np.dot(0.5, math.atan2(num, den))
    if (mth < 0):
        mth = mth + np.pi
    return mth

我正在附加示例文件here。包含所有三个文件 temp.mat、dEnergy.mat 和 th.mat

【问题讨论】:

  • 对于标量,您不需要使用 np.dot。你们真的有相同的数字吗?
  • 那不会有任何区别。 np.dot 的出现是因为我用来将 mat 文件转换为 py 文件的翻译器。
  • 也不应该需要双倍的np.sum
  • 是的,已经删除了这些

标签: python arrays matlab floating-accuracy


【解决方案1】:

无法重现:

MATLAB

>> load('temp.mat')
>> whos temp
  Name      Size            Bytes  Class     Attributes

  temp      1x32              256  double              

>> sum(temp)
ans =
   1.2189e-10
>> sprintf('%.16e', ans)
ans =
1.2188620688216985e-10

Python

>>> import numpy as np
>>> import scipy.io

>>> t = scipy.io.loadmat("temp.mat")
>>> who(t)
Name            Shape            Bytes            Type
===========================================================

temp            1 x 32           256              float64

Upper bound on total bytes  =       256

>>> np.sum(t["temp"])
1.2188620688216985e-10

编辑

响应 cmets,结果几乎相同:

马尔塔布

>> load('dEnergy.mat')
>> load('th.mat')
>> mth = compute_mean_angle(dEnergy,th);
>> sprintf('%.16e', mth)
ans =
1.5707963267948966e+00

Python

>>> m1 = scipy.io.loadmat("dEnergy.mat")
>>> m2 = scipy.io.loadmat("th.mat")
>>> compute_mean_angle(m1["dEnergy"], m2["th"])
1.5707963267948966

【讨论】:

  • 要点是:您不能只复制/粘贴输出并期望保持所有精度
  • 基于 dEnergy.mat 和 th.mat 可以看到 python 和 matlab 实现的 num 和 den 是不同的。
  • @user38751: 不,我得到完全相同的输出,请参阅我的编辑...让我再说一遍,不要从 MATLAB 复制变量的输出并将其粘贴到 Python 中,你会失去精度!从 MATLAB 将其保存为 MAT 文件,然后像我一样在 Python 中加载它。
  • 它的出现是一样的,因为 num 很小,而分母很大。所以 num/den = 0 和 0 除以 2 的 tan 倒数是 pi/2 或 1.5707。检查 num 和 den。它们变得不同了,我在这里有另一个示例,您会发现输出也不同。 (speedy.sh/eXSQY/matfiles2.rar) 这次我没有复制结果。我照你说的做了。
  • 啊现在我明白你的意思了!好吧,您看到不同结果的原因是因为浮点精度有限,加法并不是真正可交换的(a+b+c != c+b+a)。仅在 MATLAB 中,根据计算总和的方式,您可以获得两种不同的结果;例如 sum(sum(dEnergy.*sth))sum(dEnergy(:).*sth(:)) 给了我不同的结果,即使它们在数学上是等价的......这个问题可能会提供更多信息:stackoverflow.com/a/10981385/97160
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 2019-12-08
  • 2011-07-21
  • 1970-01-01
  • 2013-12-06
相关资源
最近更新 更多