フィルターのクリア

Odd behaviour of 2x2-matrix and 2x1-vector operation

2 ビュー (過去 30 日間)
Sung-Eun Jo
Sung-Eun Jo 2014 年 12 月 18 日
コメント済み: Sung-Eun Jo 2014 年 12 月 22 日
Consider a 2x2 matrix A with columns uncorrelated, and a vector x:
A = [ a b ]
[-b' a']
x = [ a']
[ b']
where a and b are complex scalar. The product of A*x is supposed to be mathematically:
A*x = [ a*a'+b*b' ] = [ a*a'+b*b' ]
[-b'*a'+a'*b'] [ 0 ]
In matlab 2012b, I tried to compare A*x matrix operation and the element-wise operations such as a*a'+b*b' and -b'*a'+a'*b'. Both results happen to be different with some random pairs of a and b. a*a'*b*b' always shows positive real, but matrix operation shows some residual on the imaginary part sometime. Even -b'*a'+a'*b' entry of matrix operation shows such erroneous imaginary part, which is supposed to be zero!
The following script finds the mismatch result and shows the hex forms of the results.
y0, y1, y2, z show the result of different operations:
  • y0 = A*x; % matlab matrix multiply script
  • y1 = mtimes(A,x); % mtimes operation
  • y2 = mvmult_lapack (A, x); % private code using lapack routine (ZGEMV)
  • z = [a*a'+b*b';-b'*a'+a'*b']; % element-wise operation
Result : y2 and z are always same and real, but y0 and y1 have erroneous imaginary part. Note that the real parts of y0 and y1 are different from the real parts of y2 and z by eps, say a difference of the last bit of floating-point format.
Discuss and Question : It is not clear why the A*x script shows the difference from the element-wise operation. It could not be a problem with LAPACK/BLAS. There seems parser or storage register problem in machine code when the matrix operation is called. Is this only preblem with 2012b or my machine?
Test script :
randn('seed',0)
ii=0;
while 1,
ii = ii + 1;
a = randn+i*randn;
b = randn+i*randn;
%
A = [a b; -b' a'];
x = [a'; b'];
y0 = A*x;
y1 = mtimes(A,x);
y2 = mvmult_lapack (A, x);
z = [a*a'+b*b';-b'*a'+a'*b'];
if sum(y0~=z) % break when the results are different!
break
end
if ii==10000
break
end
end
ii
%
a
b
y0
y1
y2
z
y0==z
[num2hex(real(y0)), repmat(' ',[2 1]), num2hex(imag(y0))]
[num2hex(real(y1)), repmat(' ',[2 1]), num2hex(imag(y1))]
[num2hex(real(y2)), repmat(' ',[2 1]), num2hex(imag(y2))]
[num2hex(real(z)), repmat(' ',[2 1]), num2hex(imag(z))]
Output :
ii =
1
a =
1.16495351050066 + 0.626839082632431i
b =
0.0750801546776829 + 0.351606902768522i
y0 =
1.87930836084417 - 3.46944695195361e-18i
0 - 2.08166817117217e-17i
y1 =
1.87930836084417 - 3.46944695195361e-18i
0 - 2.08166817117217e-17i
y2 =
1.87930836084417
0
z =
1.87930836084417
0
ans =
0
0
ans =
3ffe11a5a4cecd1e bc50000000000000
0000000000000000 bc78000000000000
ans =
3ffe11a5a4cecd1e bc50000000000000
0000000000000000 bc78000000000000
ans =
3ffe11a5a4cecd1d 0000000000000000
0000000000000000 0000000000000000
ans =
3ffe11a5a4cecd1d 0000000000000000
0000000000000000 0000000000000000
  1 件のコメント
Stephen23
Stephen23 2014 年 12 月 19 日
Maybe you should start a Newsgroup thread about this... it seems like an interesting issue to discuss.

サインインしてコメントする。

採用された回答

Roger Stafford
Roger Stafford 2014 年 12 月 20 日
Both the differences in real parts and the spurious imaginary parts in y0 and y1 are extremely small and are undoubtedly due to rounding differences in the four different methods of computation. Your results show that the real parts differ only in the least significant bits and the imaginary parts are likewise extremely small.
You should realize that simply rearranging the ordering of computations can result in slightly differing results. An example I like to give is:
format hex
(3/14+3/14)+15/14 --> 3ff8000000000000
3/14+(3/14+15/14) --> 3ff7ffffffffffff
Although both should have 1.5 as a result, the second one comes out one bit different from that. That is because there are two operations performed with a rounding after each one, and this is done in a different order in the two cases with a resulting difference in the final result.
The same applies to the operations performed in your four methods. The sequencing of operations is different in the four methods and the results therefore don't exactly match. This is something that has to be accepted in performing numerical computations using digital computers with a finite number of bits accuracy.
  3 件のコメント
Roger Stafford
Roger Stafford 2014 年 12 月 20 日
The ordering (grouping) for the imaginary part
( (br*ai) + (bi*ar) ) + ( (-ar*bi) + (-ai*br) )
should always produce an exact zero in matlab. That is because two-operand addition and multiplication are always commutative in the IEEE 754 standard. However the ordering
( ( (br*ai) + (bi*ar) ) + (-ar*bi) ) + (-ai*br)
or other similar orderings could easily yield a nonzero, (though of course an extremely small one,) because the associative law does not always hold. Something like the latter method is therefore probably what 'mtimes' is using.
Sung-Eun Jo
Sung-Eun Jo 2014 年 12 月 22 日
I agree. In matlab, 'mtimes' and * operator for complex data should be careful. Their computation ordering may cause numerical errors even in trivial cases such as perfect zero or real value expected.

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeDirect Search についてさらに検索

製品

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by