应优先选用ColPivHouseholderQR而非FullPivLU:前者数值更稳定、速度快2–3倍、自动列主元且支持solve(),仅在需精确求秩或零空间时才选FullPivLU。

直接用 FullPivLU 还是 ColPivHouseholderQR?
多数情况下别硬上 FullPivLU——它虽能处理奇异矩阵,但数值稳定性差、速度慢,且默认不检查秩。真遇到病态或近似奇异的 A,ColPivHouseholderQR 更靠谱:自动列主元、对条件数不敏感、支持 solve() 接口,且比 FullPivLU 快 2–3 倍。
只有当你明确需要精确判断秩(比如做零空间分析),才考虑 FullPivLU 或 CompleteOrthogonalDecomposition。
-
A是良态方阵 → 优先用PartialPivLU(最快) -
A是矩形或可能病态 → 用ColPivHouseholderQR -
A确实奇异且需零空间 → 改用FullPivLU并调用kernel()
为什么 inverse() 不该用来解 Ax=b?
写 x = A.inverse() * b 看起来直白,但实际做了两件危险的事:先算整个逆矩阵(O(n³)),再乘向量(O(n²)),而直接分解后求解只需 O(n²)。更糟的是,inverse() 对病态矩阵完全不鲁棒——哪怕 A 条件数是 1e8,inverse() 可能返回毫无意义的数值,而 ColPivHouseholderQR::solve() 会给出带警告的最小二乘解。
Eigen 官方文档也明确说:inverse() 仅用于教学或极小矩阵(n
立即学习“C++免费学习笔记(深入)”;
- 永远用
decomposition.solve(b),不是A.inverse() * b - 如果必须看逆矩阵,用
decomposition.matrixL().inverse() * decomposition.matrixU().inverse()(仅限 LU)也不推荐
ColPivHouseholderQR 的 solve() 返回空矩阵?
这通常不是 bug,而是 A 列数 ≠ b 行数,或 A 列满秩但行数 solve() 默认返回最小范数解;但如果 A 行数 VectorXd。
安全做法是始终检查返回值有效性:
auto qr = A.colPivHouseholderQr();
auto x = qr.solve(b);
if (x.size() == 0) {
std::cerr << "Solve failed: A.rows=" << A.rows() << ", A.cols=" << A.cols()
<< ", b.size=" << b.size() << "\n";
return;
}- 确保
A.cols() == x.size()且A.rows() == b.size() - 欠定系统(A 行数 qr.solve(b) 默认返回最小范数解,无需额外配置
- 超定系统(A 行数 > 列数)下,它自动转为最小二乘解
编译时链接和头文件怎么配才不报错?
Eigen 是纯头文件库,不需要链接 .a/.so,但容易栽在两个地方:头文件路径和模板实例化。常见错误如 error: 'solve' is not a member of 'Eigen::ColPivHouseholderQR<...>',其实是没包含完整头文件。
正确姿势:
- 只加
#include <Eigen/Dense>,别拆成#include <Eigen/QR>等零碎头文件(除非你确定自己在做什么) - CMake 中不用
target_link_libraries,只需target_include_directories(your_target PRIVATE /path/to/eigen) - 如果用
auto推导分解对象,确保所有模板参数可推导;否则显式写全类型,例如ColPivHouseholderQR<MatrixXd> qr(A);
最简能跑通的完整例子就三行初始化 + 一行求解,其余全是类型声明和检查——复杂度藏在矩阵本身,不在接口里。


















