当将表达式存储到局部变量中时,我得到了这个意外的(并且似乎是非抱怨的)浮点精度损失,特别是复杂值,同一语句在“脚本”范围内正确运行
(目前在Matlab-2018a Linux上测试,看起来像个bug,尚未在其他版本上测试过)
计算存储表达式transpose(a)*conj(a)
,其中a
是复数矩阵。存储等效的conj(a'*a)
工作没有问题,但我想了解这个问题,我从一个同事的更大的代码库中提取了这个,这得到了意想不到的结果。
在这个例子中,我使用ishermitian()
来查看是否发生了意外行为,因为这些表达式按照定义给出了Hermitian矩阵,并且兼容的浮点舍入语义即使在失去精度时也会保持它的隐士。如果矩阵是“真实的”btw,也不会发生同样的事情。
我有以下Minimal-Reproducible-Example:tst_bad()
说明了不良行为版本
len = 16; % generate complex input:
t = 2*pi/len*(0:len-1)';
tt = t + (0:0.1:0.3);
a = hilbert(sin(tt));
% a = rand(len, 4)+1i*rand(len, 4); % alternative input, almost as good
m1 = transpose(a)*conj(a);
res = -ones(1, 4);
res(1) = ishermitian(m1);
[res(2) m2] = tst_bad(a);
[res(3) m3] = tst_good(a);
m4 = single(m1);
res(4) = ishermitian(m4)
display(res)
% 1 0 1 1
function [f, m] = tst_bad(a)
m = transpose(a)*conj(a);
f = ishermitian(m);
m_iseq = isequal(m, transpose(a)*conj(a)) % 'true' but :
% running "isequal(m, transpose(a)*conj(a))" in the REPL will return
% 'false' if running in matlab-debugger
end
function [f, m] = tst_good(a)
m = conj(a'*a);
f = ishermitian(m);
end
有没有人见过任何类似的行为?请注意,即使是生病的m2
矩阵的对角线成员 - 也不是真实的(如预期的那样)
后果:
Cris Luengo
的回复的重要说明 - “函数”代码在当前的Matlab引擎中主要是JIT
'd,而“脚本”代码 - 通常不是,因此不同。您可以将测试简化为:
len = 16;
t = 2*pi/len*(0:len-1)';
tt = t + (0:0.1:0.3);
a = hilbert(sin(tt));
m1 = transpose(a)*conj(a);
disp(ishermitian(m1)) % true
m2 = tst_bad(a);
disp(ishermitian(m2)) % false
disp(isequal(m1,m2)) % false
function m = tst_bad(a)
m = transpose(a)*conj(a);
end
我刚刚在MATLAB R2018b(在线版本)上运行它并确认问题。在函数内或函数外计算transpose(a)*conj(a)
会导致不同的结果。这看起来像是JIT的一个问题。
我建议你submit this as a bug to the MathWorks。 (“报告错误”链接是蓝色条下方最右边的链接,您需要有效的许可证才能以这种方式报告错误。)