Matlab决定函数出错了

时间:2012-01-07 01:19:56

标签: matlab

以下是我的一个节目的摘录:

function [P] = abc(M,f); if det(M) ~= 1, disp(['Matrix M should have determinant 1'])

我允许用户选择不输入'f'的值。

当我运行abc([2 1; 1 1])时,程序运行正常并且它完成了它应该做的事情。但是当我运行abc([6 13; 5 11])时,我被告知“矩阵M应该有行列式1”。

地球上发生了什么?

编辑:在命令窗口中,我输入了以下内容:

M = [6 13; 5 11]; if det(M) ~= 1, disp('Im broken'); end

然后Matlab告诉我自己它已经坏了。

由于

3 个答案:

答案 0 :(得分:8)

欢迎来到浮点运算奇妙的古怪世界。 MATLAB使用LU分解(即线性代数)计算行列式。这是因为决定因素对于即使是温和大小的阵列也是非常低效的,除非它确实如此。

LU分解的结果是,行列式被计算为浮点数。这不是一个问题,除非你输入的问题像你一样简单 - 只有小整数组成的2x2矩阵的决定因素。在这种情况下,行列式本身也将是(合理的)小整数。因此,您可以通过使用教科书公式自行计算2x2矩阵的行列式来解决问题。

D = A(1,1)* A(2,2)-A(1,2)* A(2,1);

这对于小整数矩阵A来说是完全正确的,尽管这可能会显示某些矩阵的某些精度损失。例如,考虑简单的2x2矩阵A:

>> A = [1e8 1;1 1e8];

我们知道这个矩阵的行列式是1e16-1。

>> det(A)
ans =
                     1e+16

当然,MATLAB将其显示为1e16。但实际上,MATLAB中det函数生成的数字实际上是9999999999999998,所以1e16-2。很糟糕的是,如果我使用上面给出的2x2行列式的公式,它将返回一个仍然不正确的结果,10000000000000000。两个结果都是1.您可以通过查看eps的帮助了解有关这些问题的更多信息

我的观点是,有一些2x2矩阵,即使它们是整数矩阵,行列式的计算也只会有问题。

一旦你的矩阵变成非整数,那么事情确实变成了真正的浮点数,而不是整数。这意味着你只需要使用对它们的公差进行比较,而不是测试精确的统一性。无论如何,这是一个很好的规则。在进行平等测试时总是使用容忍度,至少在你学会了足够的时间知道什么时候不遵守这条规则之前!

所以,你可以选择这样的测试:

if abs(det(A) - 1) < (10*eps(1))
  warning('The sky is falling! det has failed me.')
end

请注意,我已经使用了eps(1),因为我们将事物与1进行比较。我将eps乘以10的事实允许在行列式的计算中略微倾斜。

最后,你应该知道,无论你在这里使用决定因素做什么测试,通常都要做BBBBBBBBBBAAAAAAAAAADDDDDDDD!是的,也许你的老师告诉你这样做,或者你在教科书中找到了什么。但决定因素对于数值计算来说只是一件坏事。决定因素几乎总是替代品。同样,这被称为判断,知道你被告知使用的时间实际上是错误的。

答案 1 :(得分:4)

由于浮点数的限制,您遇到了标准问题。 det函数的结果可能类似于1.000000001。

一般经验法则:永远不要测试浮点值是否相等。

答案 2 :(得分:0)

为了让您了解:det不是使用您在线性代数中研究的旧公式计算的,而是使用更有效的算法。

例如,使用Gaussian elimination,您可以在等效的上三角矩阵中变换M,然后将行列式计算为主对角线的乘积(下三角全部为零)。

M = [6 13; 5 11]
G = M - [0 0; M(2,1)/M(1,1) * M(1,:)];

理论上det(M)等于det(G),即6 * 1/6 = 1,但是G 浮点而不是真实数字矩阵,G(1,1)*G(2,2)~=1

实际上G(1,1)G(2,2)并不完全是1和1/6,但它们的相对误差非常小(请参阅eps,在大多数机器上约为2.22e- 16)。它们的实际值约为6 *(1 + eps)和1/6 *(1 + eps),因此它们的产品也会有一个小错误。

我不确定Matlab是使用高斯消元还是类似的LU decomposition