Eigen特征向量按特征值排序:std::sort测试可用VS2015编译失败
在Eigen中按特征值对特征向量排序(适配VS2015)
我之前也踩过VS2015下Eigen特征向量排序的编译坑,结合你提到的「按特征值排序→记录顺序→重排特征向量」的核心思路,给你一个能在VS2015中正常编译运行的实现方案:
核心思路拆解
你说的逻辑完全正确:
- 第一步:获取特征值数组和对应的特征向量矩阵
- 第二步:对特征值进行排序,同时记录每个特征值原来的索引位置
- 第三步:根据记录的索引,重新排列特征向量矩阵的列(Eigen中每个特征向量对应矩阵的一列)
适配VS2015的完整实现
VS2015对C++11的部分特性支持有细节限制(比如不能直接在std::sort中捕获Eigen容器的引用),所以我们用索引数组排序的方式来规避这个问题:
#include <Eigen/Dense> #include <algorithm> #include <vector> // 按特征值降序排序特征向量(要升序的话,把>改成<即可) void sortEigenvectorsByEigenvalues(Eigen::MatrixXd& eigenvectors, Eigen::VectorXd& eigenvalues) { // 创建索引数组,初始为0,1,2,...,n-1 std::vector<int> indices(eigenvalues.size()); for (int i = 0; i < indices.size(); ++i) { indices[i] = i; } // 按特征值大小对索引排序(降序) std::sort(indices.begin(), indices.end(), [&eigenvalues](int a, int b) { return eigenvalues(a) > eigenvalues(b); }); // 根据排序后的索引,重新排列特征向量矩阵和特征值向量 Eigen::MatrixXd sortedEigenvectors = eigenvectors; Eigen::VectorXd sortedEigenvalues = eigenvalues; for (int i = 0; i < indices.size(); ++i) { sortedEigenvectors.col(i) = eigenvectors.col(indices[i]); sortedEigenvalues(i) = eigenvalues(indices[i]); } // 替换原矩阵和向量 eigenvectors.swap(sortedEigenvectors); eigenvalues.swap(sortedEigenvalues); } // 测试代码 int main() { // 构造一个对称矩阵用于测试 Eigen::MatrixXd mat(3, 3); mat << 1, 2, 3, 2, 4, 5, 3, 5, 6; // 对称矩阵用SelfAdjointEigenSolver更高效 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> solver(mat); Eigen::MatrixXd eigenvectors = solver.eigenvectors(); Eigen::VectorXd eigenvalues = solver.eigenvalues(); std::cout << "排序前特征值:\n" << eigenvalues << "\n\n"; std::cout << "排序前特征向量矩阵:\n" << eigenvectors << "\n\n"; // 调用排序函数 sortEigenvectorsByEigenvalues(eigenvectors, eigenvalues); std::cout << "排序后特征值(降序):\n" << eigenvalues << "\n\n"; std::cout << "排序后特征向量矩阵:\n" << eigenvectors << "\n"; return 0; }
针对VS2015的编译注意事项
- 确保项目开启C++11支持:右键项目→属性→C/C→语言→C标准,选择
ISO C++11 标准 (/std:c++11) - 如果是非对称矩阵,不要用
SelfAdjointEigenSolver,改用EigenSolver,注意此时特征值可能是复数,需要调整排序逻辑(比如按实部大小排序)
关于你提到的测试代码补充
你写的结构体测试逻辑和我们的索引排序思路完全匹配,只是把结构体换成了特征值的索引和对应值:
#include <algorithm> struct a { double num1; int num2; }; bool acompare(a lhs, a rhs) { return lhs.num1 > rhs.num1; // 按num1降序排序 }
内容的提问来源于stack exchange,提问作者user3533030
相关产品推荐
相关产品推荐

