【问题标题】:Matrix-multiply giving two different answers矩阵乘法给出两个不同的答案
【发布时间】:2013-12-09 15:59:55
【问题描述】:

下面是一些简单的代码,显示了我所看到的:

A = randn(1,5e6)+1i*randn(1,5e6);
B = randn(1,5e6)+1i*randn(1,5e6);

sum(A.*conj(B)) - A*B'
sum(A.*conj(B)) - mtimes(A,B')
A*B' - mtimes(A,B')

现在,底部显示的三种方法应该做同样的事情,所以答案应该是零,对吧?错误的!差异很小,尽管还不够小,我认为它们可以忽略不计。此外,误差随着A和B长度的增加而增加。

有谁知道这些方法之间的实际区别是什么?我知道代码中可能写入了快捷方式,但如果可能的话,我想对其进行量化。 Matlab 会在任何地方发布差异吗?我环顾四周,但没有找到任何东西。

【问题讨论】:

  • 在 Octave 中它们都是零(即使是 format long g)...
  • @am304 既然你有八度:你能试试A*B' - fliplr(A)*fliplr(B)'吗?
  • ans = -1.31512933876365e-009 - 1.06410880107433e-010i 所以不是零...
  • @am304 谢谢。这支持了我的猜测,即 OP 中描述的错误是由 Matlab 内部选择不同的操作顺序引起的
  • 使用有限精度时最终会出现错误。请记住,您发现的两种解决方案可能都是“错误的”。如果您需要更精确,可以尝试使用符号工具箱。

标签: matlab matrix-multiplication


【解决方案1】:

这可能与执行操作的顺序有关。例如,

sum(A.*conj(B)) - fliplr(A)*fliplr(B)'

给出的结果不同于

sum(A.*conj(B)) - A*B'

或者,更引人注目的是,

A*B' - fliplr(A)*fliplr(B)'

给出非零结果,与您的测试顺序相同。

所以我敢打赌,根据方法(sum*),Matlab 在内部以不同的顺序执行操作,这很可能解释了您观察到的不同舍入误差。

【讨论】:

    【解决方案2】:

    给定每个数字的大小,对这个数字进行简单运算的舍入误差约为 10^-14

    你有 5*10^6 个数字,因此如果你真的很不幸,舍入误差可能会变成 5*10^-8。

    您观察到的错误大小为 10^10,完全在预期范围内。

    请注意,差异不是由复杂转置引起的,而是由总和与矩阵乘积的乘积引起的。

    A = randn(1,5e6)+1i*randn(1,5e6);
    B = randn(1,5e6)+1i*randn(1,5e6);
    
    B1 = conj(B); 
    B2 = B';
    
    isequal(B1(:),B2(:)) % This returns true
    
    A*transpose(conj(B)) - A*B' % Hence this returns zero
    
    sum(A.*transpose(B')) - A*B' % But this returns something like 1e-10
    

    非复杂的AB 也会出现类似的效果:

    N=1e6;
    A = 1:N; 
    B=1:N;
    
    (N * (N + 1) * (2*N + 1))/6 % This will give exactly the right answer
    A*B' 
    fliplr(A)*fliplr(B)'
    

    请注意,两个最低的答案彼此之间仅相差几百,而实际上它们与正确答案的差距超过 2000。如果这是一个问题,请考虑使用符号工具箱。这允许您以任意精度进行计算。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 2018-10-27
      • 1970-01-01
      • 2020-11-03
      相关资源
      最近更新 更多