(Matlab)奇怪的精度损失,同时将复杂矩阵分配给局部变量

时间:2019-02-19 15:26:43

标签: matlab floating-point precision jit scoping

我遇到这种意外的(似乎是非投诉的)浮点精度损失,特别是对于复杂值,当将表达式存储到局部变量中时,同一条语句在“脚本”范围内正确运行< / p>

(当前在Matlab-2018a Linux上进行测试,似乎是一个错误,尚未在其他版本上进行测试)

计算将存储表达式transpose(a)*conj(a),其中a是一个复数矩阵。存储等效的conj(a'*a)可以正常工作,但是我想了解这个问题,我从同事的较大代码库中提取了此代码,该代码库获得了意外的结果。

在该示例中,我使用ishermitian()来查看是否发生了意外的行为,因为根据定义,这些表达式给出了Hermitian矩阵,而兼容的浮点舍入语义将使其保持为Hermitian 失去精度时。如果矩阵是“真实的”顺便说一句,则不会发生相同的事情。

我有以下“最小可复制示例”: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矩阵的对角成员-也不是真实的(按预期)


后果:

  1. @ Cris Luengo的回复中的重要注释-“功能”代码在当前的Matlab引擎中大多为JIT,而“脚本”代码通常不是,因此区别

  2. 因此,这不是任何变量作用域或属性(我已经开始尝试在'script-scope'中分配变量并将其传递给函数,等等)

  3. 几乎让我想用一种数字代码来做这种语言,在这种语言中,计算结果将这种假设体现在类型系统中(例如,陈述-这是一个Hermitian矩阵等,具体取决于代数结构)标量),并进一步使用此信息来选择算法等。

1 个答案:

答案 0 :(得分:3)

您可以将测试简化为:

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。 (“报告错误”链接是蓝色条下方最右边的链接,您需要有效的许可证才能以这种方式报告错误。)