这是我为家庭作业遇到的问题编写的matlab代码。 在 A 乘法及其转置后,根据所有同学,得到的方阵应该具有行列式零,因为他们的代码(不同的一个)给了他们。为什么我的代码没有给出 c 和 d 的行列式是无穷大
A = rand(500,1500);
b = rand(500,1);
c = (A.')*A;
detc = det(c);
cinv = inv((A.')*A);
d = A*(A.');
detd = det(d);
dinv = inv(A*(A.'));
x1 = (inv((A.')*A))*((A.')*b);
x2 = A.'*((inv(A*(A.')))*b);
这种行为在det
文档的"限制"部分中进行了解释,并在"查找奇异矩阵的行列式"小节中举例说明:
尽管
A
是单数的,但A
的决定因素还是相当大的。事实上,A
的行列式应该正好为零!d
的不准确性是由于 LU 分解的 MATLAB® 实现中舍入误差的聚合,det
使用该误差来计算行列式。
也就是说,在这种情况下,您可以使用同一页面上给出的 m 代码实现来产生所需的结果,但以升序对U
的对角线元素进行排序。 请考虑示例脚本:
clc();
clear();
A = rand(500,1500);
b = rand(500,1);
c = (A.')*A;
[L,U] = lu(c);
% Since det(L) is always (+/-)1, it doesn't impact anything
diagU = diag(U);
detU1 = prod(diagU);
detU2 = prod(sort(diagU,'descend'));
detU3 = prod(sort(diagU,'ascend'));
fprintf('Minimum: %+9.5en',min(abs(diagU)));
fprintf('Maximum: %+9.5en',max(abs(diagU)));
fprintf('Determinant:n');
fprintf('tNo Sort: %gn' ,detU1);
fprintf('tDescending Sort: %gn' ,detU2);
fprintf('tAscending Sort: %gnn',detU3);
这将产生输出:
Minimum: +1.53111e-13
Maximum: +1.72592e+02
Determinant:
No Sort: Inf
Descending Sort: Inf
Ascending Sort: 0
请注意,排序的方向很重要,并且无排序会给出Inf
,因为对角线上不存在真正的0
。 降序排序看到最大值首先乘以,显然,它们超过 realmax
并且永远不会乘以真正的0
,这将产生一个NaN
。 升序排序将所有接近零的对角线值聚集在一起,这些值很少有大的负值(事实上,更健壮的方法会根据幅度进行排序,但这里没有这样做),它们的乘法会产生一个真正的0
(意味着该值低于 IEEE-754 算术中可用的最小非规范化数字),产生"正确"的结果。
以及其他人所暗示的,我将引用原始的Matlab开发人员和Mathworks联合创始人Cleve Moler的话:
[行列式]在理论考虑和手工计算中很有用,但不能为稳健的数值软件提供坚实的基础。
好的。因此,det(A'*A) 不为零的事实并不能很好地指示 A'*A 的(非)奇点。行列式取决于缩放,矩阵显然非奇异可以具有非常小的行列式。例如,矩阵1/2 * I_n其中I_n是 nxn 恒等式的行列式为 (1/2)^n,当 n 走向无穷大时,它(快速)收敛到 0。但是 1/2 * I_n根本不是单数。
因此,检查矩阵奇点的最佳方法是条件数。
在您的情况下,在进行一些测试后
>> A = rand(500, 1500) ;
>> det(A'*A)
ans =
Inf
您可以看到(计算的)行列式显然不为零。但这实际上并不奇怪,也不应该真正困扰你。行列式相当难以计算,所以是的,它只是舍入误差。如果你想要一个更好的近似值,你可以执行以下操作
>> s = eig(A'*A) ;
>> prod(s)
ans =
0
在那里,你看到它更接近于零。
另一方面,条件数是矩阵(非)奇点的更好估计器。在这里
>> cond(A'*A)
ans =
1.4853e+20
而且,由于它比 1e+16 大得多,矩阵显然是奇异的。1e+16的原因有点乏味,但主要是由于进行浮点计算时的计算机精度。
我认为这几乎只是一个四舍五入的问题,Inf 并不意味着你得到无穷大作为答案,只是你的行列式真的很大并且超过了realmax
。正如Adiel所说,A*A.生成一个对称矩阵,并且应该有一个行列式的数值。例如,设置:
A=rand(5,15)
你应该发现 A*A." 的 det 只是一个数值。
那么,你的朋友是如何得到零的,那么对于det
个大矩阵来说,很容易得到 0 或 inf(你为什么要这样做,我不知道)。所以我认为他们只是得到了相同/类似的舍入问题。