这是一些显示我一直看到的简单代码:
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会在任何地方发布差异吗?我环顾四周,但没找到任何东西。
答案 0 :(得分:5)
这可能与执行操作的顺序有关。例如,
sum(A.*conj(B)) - fliplr(A)*fliplr(B)'
给出的结果与
不同sum(A.*conj(B)) - A*B'
或者,更引人注目的是,
A*B' - fliplr(A)*fliplr(B)'
给出非零结果,与测试的顺序相同。
所以我的赌注是,取决于方法(sum
或*
),Matlab内部以不同的顺序执行操作,这可能会导致您观察到的不同舍入错误。
答案 1 :(得分: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
非复杂A
和B
:
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个。如果这是一个问题,请考虑使用符号工具箱。这允许您以任意精度计算。