赞
踩
线性代数在3D游戏建模、深度学习、机器人工程、视频图像处理、航空航天等领域都有着举足轻重的位置。在使用C++编程时,如果从零编写矩阵的乘法、求逆、求特征值等运算,将会是件很麻烦的事情。而且,不管是从计算正确性,还是从效率方面都很难得到保障。因此,成熟稳定的线性代数库显得尤为重要。
Eigen是线性代数的C++模板库,它包含矩阵、向量、四元数、数值求解器和相关算法,其拥有良好的稳定性和计算效率,是我们搭建C++工程研究算法的必备利器。
目录
通过官网下载,然后解压到自己指定的目录即可。在进行VS工程配置时,只需要如下图那样包含Eigen库所在目录即可。
右击工程名——》属性——》VC++目录——》常规——》包含目录
常用的向量类型有 Vector3d Vector4d VectorXd VectorXcd等。其中VectorXd 表示实数向量,VectorXcd 表示复数向量,前者应用在许多科学计算和工程中,如物理模拟、信号处理等,后者在需要处理复数时应用,如电磁学、量子物理等。
- Vector3d v3d_a = { 1,2,3 };
- cout << "Vector3d构造一:\n" << v3d_a << endl;
- Vector3d v3d_b;
- v3d_b << 4, 5, 6;
- cout << "Vector3d构造二:\n" << v3d_b << endl;
- Vector4d v4d = { 1.1,2.2,3.3,4.4 };
- cout << "Vector4d:\n" << v4d << endl;
- VectorXd vxd(8); //这里一定要指定向量长度,否则报错!
- vxd << 3, 1, 4, 1, 5, 9, 2, 6;
- cout << "VectorXd:\n" << vxd << endl;
- VectorXcd xcd(3, 1);
- xcd.setZero();
- xcd[0]._Val[0] = 1.2;
- xcd[2]._Val[1] = 1.3;
- cout << "VectorXcd:\n" << xcd << endl;
- cout << "VectorXcd real:\n" << xcd.real() << endl;
- Vector3d v3d_a = { 1,2,3 };
- cout << "二范数:\n" << v3d_a.norm() << endl;
- Vector3d v3d_a = { 1,2,3 };
- Vector3d v3d_b;
- v3d_b << 4, 5, 6;
- cout << "点积:\n" << v3d_a.dot(v3d_b) << endl;
- Vector3d v3d_a = { 1,2,3 };
- Vector3d v3d_b;
- v3d_b << 4, 5, 6;
- cout << "叉积:\n" << v3d_a.cross(v3d_b) << endl;
- MatrixXd I = MatrixXd::Identity(4, 4);
- cout << "单位矩阵:\n" << I << endl;
- MatrixXd MatA(3, 3);
- MatA << 1, 2, 3,
- 4, 5, 6,
- 7, 8, 9;
- cout << "矩阵的迹:\n" << MatA.trace() << endl;
cout << "矩阵的转置:\n" << MatA.transpose() << endl;
大小为 (p,q)
, 起始于 (i,j)
的块
动态大小的块表达式 matrix.block(i,j,p,q);
固定大小的块表达式matrix.block<p,q>(i,j);
二者区别是,固定大小的版本会在块比较小的时候快一点,但要求块大小在编译的时候就知道。
- MatrixXd MatB(3, 3);
- Vector3d va = { 0.1,0.4,0.7 };
- Vector3d vb = { 0.2,0.5,0.8 };
- Vector3d vc = { 0.3,0.6,0.9 };
- MatB.block<3, 1>(0, 0) = va; //固定 从0编码,以0,0为起点,存入3行1列的向量
- MatB.block(0, 1, 3, 1) = vb; //动态 从0编码,以0,1为起点,存入3行1列的向量
- MatB.block<3, 1>(0, 2) = vc;
- cout << "块操作:\n" << MatB << endl;
cout << "矩阵乘法:\n" << MatA * MatB << endl;
- MatrixXd MatC(3, 3);
- MatC << 1, 2, 3,
- 2, 5, 6,
- 3, 4, 8;
- cout << "矩阵求逆:\n" << MatC.inverse() << endl;
- MatrixXd K(4, 4);
- K << -0.504129, 0.0190935, -0.836998, -0.137961,
- 0.0190935, -0.534845, 0.114843, -0.813407,
- -0.836998, 0.114843, 0.526649, -0.0167767,
- -0.137961, -0.813407, -0.0167767, 0.512325;
- VectorXd eigVals = K.eigenvalues().real();
- cout << "特征值:\n" << eigVals << endl;
- // 求解矩阵的最大特征值和对应特征向量
- EigenSolver<MatrixXd> es(K);
- MatrixXcd eigenvectors = es.eigenvectors();
- int index_of_max = MaxElementIndex(eigVals); // 找到最大特征值对应的下标
- VectorXcd max_eigenvector = eigenvectors.col(index_of_max);
- Vector4d vec4 = max_eigenvector.real();
- cout << "最大特征值对应的特征向量:\n" << vec4 << endl;
- Quaterniond q(4, 1, 2, 3);//要注意Eigen中四元数赋值的顺序,实数w在首;
- cout << "四元数:\n" << q << endl; //但是实际上它的内部存储顺序是[x y z w]
- cout << q.w() << " " << q.x() << " " << q.y() << " " << q.z() << endl; //单个取值
- q = vec4;
- cout << "旋转矩阵:\n" << q.toRotationMatrix() << endl; //将四元数转换为旋转矩阵
在用VS断点调试一般变量时,只需要鼠标悬停在变量上即可看见变量值,但由于矩阵和向量都是一个抽象对象,若要观察其具体变量就需要使用“快速监视“窗口,并且编辑表达式,使数据内容完全展开。
双击选中变量
Shift+F9
一直展开到array,就可以看见向量全部内容
同理,选中变量,Shift+F9,打开快速监视
此时展开到m_data变量,发现只能看到一个数值,这是因为该变量是个double指针类型
为了观察整个矩阵,在表达式栏,输入”,16”,表示展开指针后面16个数值,如下
敲击两次回车
认真比对存储顺序发现——矩阵元素存储按列依次排列,而非按行依次排列!
- #include <iostream>
- #include <Eigen/Core>
- #include <Eigen/Geometry>
- #include <Eigen/Eigenvalues>
- #include <Eigen/Dense>
-
- using namespace std;
- using namespace Eigen;
-
- int MaxElementIndex(VectorXd v)
- {
- int index = 0;
- for (int i = 1; i < v.size(); i++)
- {
- if (v(index) < v(i))
- {
- index = i;
- }
- }
- return index;
- }
-
- int main()
- {
- Vector3d v3d_a = { 1,2,3 };
- cout << "Vector3d构造一:\n" << v3d_a << endl;
- Vector3d v3d_b;
- v3d_b << 4, 5, 6;
- cout << "Vector3d构造二:\n" << v3d_b << endl;
-
- cout << "二范数:\n" << v3d_a.norm() << endl;
- cout << "点积:\n" << v3d_a.dot(v3d_b) << endl;
- cout << "叉积:\n" << v3d_a.cross(v3d_b) << endl;
-
- Vector4d v4d = { 1.1,2.2,3.3,4.4 };
- cout << "Vector4d:\n" << v4d << endl;
-
- VectorXd vxd(8); //这里一定要指定向量长度,否则报错!
- vxd << 3, 1, 4, 1, 5, 9, 2, 6;
- cout << "VectorXd:\n" << vxd << endl;
-
- VectorXcd xcd(3, 1);
- xcd.setZero();
- xcd[0]._Val[0] = 1.2;
- xcd[2]._Val[1] = 1.3;
- cout << "VectorXcd:\n" << xcd << endl;
- cout << "VectorXcd real:\n" << xcd.real() << endl;
-
- MatrixXd I = MatrixXd::Identity(4, 4);
- cout << "单位矩阵:\n" << I << endl;
- MatrixXd MatA(3, 3);
- MatA << 1, 2, 3,
- 4, 5, 6,
- 7, 8, 9;
- cout << "矩阵的迹:\n" << MatA.trace() << endl;
- cout << "矩阵的转置:\n" << MatA.transpose() << endl;
-
- MatrixXd MatB(3, 3);
- Vector3d va = { 0.1,0.4,0.7 };
- Vector3d vb = { 0.2,0.5,0.8 };
- Vector3d vc = { 0.3,0.6,0.9 };
- MatB.block<3, 1>(0, 0) = va; //固定 从0编码,以0,0为起点,存入3行1列的向量
- MatB.block(0, 1, 3, 1) = vb; //动态 从0编码,以0,1为起点,存入3行1列的向量
- MatB.block<3, 1>(0, 2) = vc;
- cout << "块操作:\n" << MatB << endl;
- cout << "矩阵乘法:\n" << MatA * MatB << endl;
-
- MatrixXd MatC(3, 3);
- MatC << 1, 2, 3,
- 2, 5, 6,
- 3, 4, 8;
- cout << "矩阵求逆:\n" << MatC.inverse() << endl;
-
- MatrixXd K(4, 4);
- K << -0.504129, 0.0190935, -0.836998, -0.137961,
- 0.0190935, -0.534845, 0.114843, -0.813407,
- -0.836998, 0.114843, 0.526649, -0.0167767,
- -0.137961, -0.813407, -0.0167767, 0.512325;
- VectorXd eigVals = K.eigenvalues().real();
- cout << "特征值:\n" << eigVals << endl;
-
- // 求解矩阵的最大特征值和对应特征向量
- EigenSolver<MatrixXd> es(K);
- MatrixXcd eigenvectors = es.eigenvectors();
- int index_of_max = MaxElementIndex(eigVals); // 找到最大特征值对应的下标
- VectorXcd max_eigenvector = eigenvectors.col(index_of_max);
- Vector4d vec4 = max_eigenvector.real();
- cout << "最大特征值对应的特征向量:\n" << vec4 << endl;
-
- Quaterniond q(4, 1, 2, 3);//要注意Eigen中四元数赋值的顺序,实数w在首;
- cout << "四元数:\n" << q << endl; //但是实际上它的内部存储顺序是[x y z w]
- cout << q.w() << " " << q.x() << " " << q.y() << " " << q.z() << endl; //单个取值
- q = vec4;
- cout << "旋转矩阵:\n" << q.toRotationMatrix() << endl; //将四元数转换为旋转矩阵
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。