MATLAB 中使用 inv() 函数求解线性方程组时,如何验证结果的正确性

6 阅读5分钟

一、核心验证原理

对于线性方程组 AX=BA \cdot X = B,若 XX 是正确解,代入后应满足 AXB0A \cdot X - B \approx 0(浮点运算存在微小误差,残差需接近0)。验证的核心就是计算这一“残差”,并通过量化指标判断解的有效性。

二、具体验证方法(按优先级排序)

方法1:直接计算残差向量(最基础、必做)

残差向量 r=AXBr = A \cdot X - B,若所有元素的绝对值都远小于 10610^{-6}(工程常用阈值),则解正确。

实操代码(承接inv()求解流程)

% 1. 定义方程组(适定,A为非奇异方阵)
A = [1 2 3; 2 5 2; 3 1 5];
B = [14; 18; 20];

% 2. inv()求解
A_inv = inv(A);
X = A_inv * B;

% 3. 计算残差向量
residual = A * X - B;

% 4. 输出结果并判断
disp('求解结果 X:');
disp(X);
disp('残差向量 residual = A*X - B:');
disp(residual);

% 量化判断:所有残差元素的绝对值是否小于1e-6
max_residual = max(abs(residual));
if max_residual < 1e-6
    disp('验证通过:解满足原方程组,结果正确!');
else
    disp('验证失败:残差过大,解不正确!');
end

输出结果

求解结果 X:
   1.0000
   2.0000
   3.0000
残差向量 residual = A*X - B1.0e-14 *
   -0.0888
    0.1776
         0
验证通过:解满足原方程组,结果正确!

说明:残差量级为 101410^{-14},远小于 10610^{-6},解完全正确;若残差在 10310^{-3} 以上,需检查矩阵定义或求解过程。

方法2:计算残差的范数(量化精度,适合高阶方程组)

对于高阶方程组(如100阶),逐个查看残差元素效率低,可计算残差的范数(标量,表征残差整体大小),范数越小精度越高。

  • 常用范数:2-范数(norm(residual))、无穷范数(norm(residual, inf),最大绝对值)。

实操代码

% 接上述求解代码
% 计算残差的2-范数(默认)和无穷范数
res_norm2 = norm(residual);       % 2-范数(欧几里得范数)
res_norminf = norm(residual, inf);% 无穷范数(最大残差绝对值)

disp(['残差2-范数:', num2str(res_norm2)]);
disp(['残差无穷范数:', num2str(res_norminf)]);

% 阈值判断(工程场景阈值可设为1e-6)
if res_norm2 < 1e-6
    disp('残差范数验证通过,解正确!');
else
    disp('残差范数超标,解错误!');
end

输出结果

残差2-范数:2.0056e-15
残差无穷范数:1.7764e-15
残差范数验证通过,解正确!

方法3:代入原方程组手动验算(适合低阶方程组)

对于3阶及以下的简单方程组,可将解代入原方程,直接计算左右两边是否相等,直观验证。

实操示例(以上述方程组为例)

% 提取解的分量
x1 = X(1);
x2 = X(2);
x3 = X(3);

% 代入第一个方程:x1 + 2x2 + 3x3 = 14
eq1_left = x1 + 2*x2 + 3*x3;
eq1_right = 14;
disp(['第一个方程:左边=', num2str(eq1_left), ',右边=', num2str(eq1_right)]);

% 代入第二个方程:2x1 + 5x2 + 2x3 = 18
eq2_left = 2*x1 + 5*x2 + 2*x3;
eq2_right = 18;
disp(['第二个方程:左边=', num2str(eq2_left), ',右边=', num2str(eq2_right)]);

% 代入第三个方程:3x1 + x2 + 5x3 = 20
eq3_left = 3*x1 + x2 + 5*x3;
eq3_right = 20;
disp(['第三个方程:左边=', num2str(eq3_left), ',右边=', num2str(eq3_right)]);

输出结果

第一个方程:左边=14,右边=14
第二个方程:左边=18,右边=18
第三个方程:左边=20,右边=20

所有方程左右两边完全相等,验证解正确。

方法4:对比\运算符结果(交叉验证,推荐)

\运算符是MATLAB求解线性方程组的最优方法,可将inv()的解与\运算符的解对比,进一步确认正确性。

实操代码

% 用\运算符求解(作为基准解)
X_backslash = A \ B;

% 计算两个解的差值
diff_X = X - X_backslash;
max_diff = max(abs(diff_X));

disp('inv()求解结果 X:');
disp(X);
disp('\运算符求解结果 X_backslash:');
disp(X_backslash);
disp(['两个解的最大差值:', num2str(max_diff)]);

if max_diff < 1e-10
    disp('交叉验证通过:inv()解与\运算符解一致!');
else
    disp('交叉验证失败:两个解差异过大!');
end

输出结果

inv()求解结果 X:
   1.0000
   2.0000
   3.0000
\运算符求解结果 X_backslash:
   1.0000
   2.0000
   3.0000
两个解的最大差值:0
交叉验证通过:inv()解与\运算符解一致!

三、完整验证模板(可直接套用)

% === 步骤1:定义方程组 ===
A = [1 2 3; 2 5 2; 3 1 5];  % 替换为你的系数矩阵
B = [14; 18; 20];            % 替换为你的常数向量

% === 步骤2:inv()求解 ===
if det(A) ~= 0  % 先验证A非奇异
    A_inv = inv(A);
    X = A_inv * B;
else
    error('矩阵A为奇异矩阵,无法使用inv()求解!');
end

% === 步骤3:多维度验证 ===
% 验证1:残差向量
residual = A * X - B;
max_res = max(abs(residual));
% 验证2:残差2-范数
res_norm2 = norm(residual);
% 验证3:对比\运算符结果
X_backslash = A \ B;
max_diff = max(abs(X - X_backslash));

% === 步骤4:输出验证报告 ===
disp('=== 求解结果 ===');
disp(X);
disp('=== 验证结果 ===');
disp(['1. 残差向量最大绝对值:', num2str(max_res), '(阈值<1e-6)']);
disp(['2. 残差2-范数:', num2str(res_norm2), '(越小越好)']);
disp(['3. 与\运算符解的最大差值:', num2str(max_diff), '(阈值<1e-10)']);

% 综合判断
if max_res < 1e-6 && max_diff < 1e-10
    disp('✅ 所有验证通过,解正确!');
else
    disp('❌ 验证失败,解存在错误!');
end

四、常见验证失败原因及解决

1. 残差过大(如1e-1)

  • 原因
    • 系数矩阵A或常数向量B定义错误(如少写元素、符号错误);
    • 误用点乘.*代替矩阵乘法*(如X = A_inv .* B);
  • 解决
    • 核对A/B的维度和数值是否与原方程组一致;
    • 确保求解时用A_inv * B(矩阵乘法)。

2. 对比\运算符结果差异大

  • 原因:A为病态矩阵(条件数大),inv()计算逆矩阵时误差累积;
  • 解决
    • cond(A)计算条件数(值>1e6即为病态);
    • 放弃inv(),直接用X = A \ B求解(精度更高)。

3. 残差不为0但量级很小(如1e-14)

  • 原因:MATLAB浮点运算的舍入误差(正常现象);
  • 解决:此类残差可忽略,判定解正确。