Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python与MATLAB——处理接近机器精度的数字_Matlab_Python 3.x_Precision - Fatal编程技术网

Python与MATLAB——处理接近机器精度的数字

Python与MATLAB——处理接近机器精度的数字,matlab,python-3.x,precision,Matlab,Python 3.x,Precision,我知道有一些帖子有类似的主题。然而,我还没有找到任何不是问题特定的、更一般的东西 请注意,我不是在寻找一种变通方法,即“if”语句,如果足够接近它,则强制值为零 在我的问题中,我看到的是将矩阵转换为Hessenberg形式的结果(即,应用转换将零引入矩阵-数学细节在这里没有问题)。我最初用MATLAB为一个类编写代码,现在也希望用Python编写代码(所有代码都使用基本操作-这里没有“黑盒”操作)。我已经成功地做到了这一点,但我得到的答案却有着微小的差异,而这些答案应该是零 例如: 一些应为零的

我知道有一些帖子有类似的主题。然而,我还没有找到任何不是问题特定的、更一般的东西

请注意,我不是在寻找一种变通方法,即“if”语句,如果足够接近它,则强制值为零

在我的问题中,我看到的是将矩阵转换为Hessenberg形式的结果(即,应用转换将零引入矩阵-数学细节在这里没有问题)。我最初用MATLAB为一个类编写代码,现在也希望用Python编写代码(所有代码都使用基本操作-这里没有“黑盒”操作)。我已经成功地做到了这一点,但我得到的答案却有着微小的差异,而这些答案应该是零

例如:

一些应为零的条目报告为1.77635684e-15和4.44089210e-16,它们都接近机器精度2.2204460E-16

这有什么根本原因吗


编辑

把我的问题再细化一点

我最后得到的是一个几乎相等的数字的减法——我知道这通常是一个坏主意——对于那些值应该为零的条目。由于它们几乎相等且非常小,因此存在某种形式的精度损失

这让我想到,MATLAB和python处理此类评估的方式可能存在差异


编辑编辑

下面是困扰我的输出(“py”=Python输出,“mat”=MATLAB输出)。我可以忍受高达15位数的差异-这是机器精度。让我烦恼的是第四栏。这里是几乎相等的数字减法发挥作用的地方,也是我们真正看到差异的地方(第2-4行彼此为负数!)


以下是我的python代码供参考:

这是我的MATLAB代码:

函数[dumA]=tridiag(A0)
%此函数将任何mxm矩阵简化为三对角形式
%通过正交相似变换。对于对称情况,则
%海森伯格的形式将是三对角的。
杜马=A0;
tmp=大小(杜马);
m=tmp(1);
v=单元(1,长度(1:m-2));
对于k=1:m-2
x=杜马(k+1:m,k);
tmp=尺寸(x);
如果符号(x(1))==0
tmpsign=1;
其他的
tmpsign=符号(x(1));
结束
dum=tmpsign*标准(x,2)*眼睛(tmp(1,1)+x;
如果和(x)==0
v{k}=dum;
持续
结束
v{k}=dum/范数(dum,2);
杜马(k+1:m,k:m)=杜马(k+1:m,k:m)-2*v{k}*(v{k}'*杜马(k+1:m,k:m));
杜马(1:m,k+1:m)=杜马(1:m,k+1:m)-2*(杜马(1:m,k+1:m)*v{k})*v{k};
结束
结束

您的python代码与编写的代码不一样,与MATLAB代码不同。我修正了它:

dumA = np.array(A)
n = np.shape(dumA)[1] # obtains n in (m,n) matrix
v = []
for k in np.arange(n-2):
    x = dumA[k+1:,k:k+1]
    tmp = np.shape(x)[0]
    tmpsign = np.sign(x[0]);
    if not tmpsign:
        tmpsign = 1.
    dum = tmpsign*norm(x,2)*np.eye(tmp,1) + x;
    if not x.sum():
        v.append(dum)
        continue
    v.append(dum/norm(dum,2));
    dumA[k+1:,k:] -= 2.*(v[k] @ (v[k].T @ dumA[k+1:,k:]));
    dumA[:,k+1:] -= 2.*((dumA[:,k+1:] @ v[k]) @ v[k].T);
print(dumA)
我做了一些测试,在第一次迭代中,直到循环的倒数第二行(分配给
杜马的倒数第二行),一切都是一样的。这个代码出现了问题:
dumA[:,k+1::@v[k]
dumA(1:m,k+1:m)*v{k}
。矩阵乘积的最后一个元素有一个非常微小的数值差异,大约为2e-16。这可能归结为略有不同的实现


MATLAB和numpy似乎都在使用同一版本的MKL进行计算,但如果看不到MATLAB源代码,就不可能准确说出差异所在。

我真的不明白你在问什么。在处理数字的浮点表示时,这是一个基本的“问题”。MATLAB已经在隐式地在数据显示中“解决”了这个问题。您所断言的值在MATLAB中也很可能不完全为零,仅显示为零。这种双精度可以存储15-17位小数,问题是什么?顺序的差异
1e-15
并不意外,我很乐意。如果您需要这些宝贵的数据,您可能需要重新考虑问题,通常避免运算量非常小和非常大以及混合和匹配。没有指定矢量化运算的执行顺序,因此机器精度顺序上的错误可能会改变。我会告诉你更多:numpy使用了一个矢量化版本的
np.dot
,它尽可能利用多个CPU核。这样就更容易看出,你最终得到的东西并不完全确定,但可以根据机器精度的大小而变化。通常的结论是:不要做任何假定浮点运算完全一致的事情。这不关你的事。与正在处理的数据相比,误差的大小在浮点数操作的预期范围内。这里没有精度损失。@符号是什么?我以前没见过。另外,什么是MKL?
@
是python矩阵乘法运算符(相当于MATLAB的
*
)。它适用于Python3.5及更高版本。MKL是Intel的数学内核库,是一个快速(至少在Intel CPU上)线性代数库,MATLAB使用,numpy和scipy可以选择使用。我测试的numpy版本Anaconda使用MKL。
dumA = np.array(A)
n = np.shape(dumA)[1] # obtains n in (m,n) matrix
v = []
for k in np.arange(n-2):
    x = dumA[k+1:,k:k+1]
    tmp = np.shape(x)[0]
    tmpsign = np.sign(x[0]);
    if not tmpsign:
        tmpsign = 1.
    dum = tmpsign*norm(x,2)*np.eye(tmp,1) + x;
    if not x.sum():
        v.append(dum)
        continue
    v.append(dum/norm(dum,2));
    dumA[k+1:,k:] -= 2.*(v[k] @ (v[k].T @ dumA[k+1:,k:]));
    dumA[:,k+1:] -= 2.*((dumA[:,k+1:] @ v[k]) @ v[k].T);
print(dumA)