C++之 Eigen-3.4.0 全方位教程:Chapter02-矩阵篇

本文详细介绍了Eigen库中的矩阵类Matrix及其关键特性,包括模板参数、构造函数、赋值、大小调整、算术运算(包括加减、标量乘除、转置、矩阵乘法和点积)、优化技巧,以及如何处理动态与固定大小矩阵。此外,还涵盖了基本算术归约操作和操作有效性检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

矩阵类(The Matrix class

Eigen 中,所有矩阵和向量都是Matrix模板类的对象。向量只是矩阵的一种特殊情况,具有 1 行或 1 列。

Matrix的前三个模板参数

矩阵类需要六个模板参数,但是现在了解前三个参数已经足够了。

剩下的三个参数有默认值,现在我们将保持不变,我们将在下面讨论

Matrix的三个强制性模板参数是:

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

  • Scalar是标量类型,即系数的类型。也就是说,如果您想要一个浮点矩阵,请在此处选择float。有关所有支持的标量类型的列表以及如何扩展对新类型的支持,请参阅标量类型。
  • RowsAtCompileTimeColsAtCompileTime是编译时已知的矩阵的行数和列数(如果在编译时不知道该数字,请参见下文了解该怎么做)。

我们提供了很多方便的 typedef 来涵盖通常的情况。例如,Matrix4f是一个 4x4 的浮点矩阵。这是Eigen定义的方式:

typedef Matrix<float, 4, 4> Matrix4f;

Eigen里面用到了很多的typedef简化名称长度,例如:

typedef Matrix<float, 3, 1> Vector3f;
typedef Matrix<int, 1, 2> RowVector2i;
typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
typedef Matrix<int, Dynamic, 1> VectorXi;

typedef Array<float,Dynamic,Dynamic>       ArrayXXf
typedef Array<double,Dynamic,1>            ArrayXd
typedef Array<int,1,Dynamic>               RowArrayXi
typedef Array<float,3,3>                   Array33f
typedef Array<float,4,1>                   Array4f
······

Tips: 虽然Eigen官方已经提供了许多命名模板,但是这是对于X <= 4 的情况比较试用,一般处理大数据时,为了尽可能的多实用固定矩阵,应该熟练掌握利用原始模板创建对象

Vector

如上所述,在Eigen 中,向量只是矩阵的一种特殊情况,具有 1 行或 1 列。他们有 1 列的情况是最常见的;这样的向量称为列向量,通常简称为向量。在它们有 1 行的另一种情况下,它们被称为行向量。

例如,方便的 typedef Vector3f是 3 个浮点数的(列)向量。它由Eigen定义如下:

typedef Matrix<float, 3, 1> Vector3f;

我们还为行向量提供方便的 typedef,例如:

typedef Matrix<int, 1, 2> RowVector2i;

The special value Dynamic

当然,Eigen不限于其维度在编译时已知的矩阵。在RowsAtCompileTime和ColsAtCompileTime模板参数可以采取特殊值Dynamic这表明大小在编译时是未知的,所以必须作为运行时变量来处理。在Eigen术语中,这样的大小被称为动态 大小;而在编译时已知的大小称为固定 大小。

例如,方便的 typedef MatrixXd 表示具有动态大小的双精度矩阵,定义如下:

typedef Matrix<double, Dynamic, Dynamic> MatrixXd;

同样,我们定义了一个动态大小的 typedef VectorXi如下:

typedef Matrix<int, Dynamic, 1> VectorXi;

还可以固定某行或某列的大小:

Matrix<float, 3, Dynamic>;

构造函数

  • 默认构造函数始终可用,从不执行任何动态内存分配,也从不初始化矩阵系数。你可以做:

Matrix3f a; //a 是一个 3×3 矩阵,带有未初始化系数的普通 float[9] 数组,

MatrixXf b; //b 是一个动态大小的矩阵,其大小当前为 0×0,并且其系数数组尚未分配。

  • 也可以使用获取尺寸的构造函数。

    对于矩阵,总是首先传递行数。对于向量,只需传递向量大小。他们分配给定大小的系数数组,但不初始化系数本身:

MatrixXf a(10,15); //a 是一个 10x15 动态大小的矩阵,具有已分配但当前未初始化的系数。

VectorXf b(30); //b 是大小为 30 的动态大小向量,具有已分配但当前未初始化的系数。

  • 为了提供跨固定大小和动态大小矩阵的统一 API,在固定大小矩阵上使用这些构造函数是合法的,即使在这种情况下传递大小是无用的。所以这是合法的:

Matrix3f a(3,3); //虽然没有意义,但是是合法的

  • 矩阵和向量也可以从系数列表中初始化。在 C++11 之前,此功能仅限于固定大小的小列或最大大小为 4 的向量:

Vector4d c(5.0, 6.0, 7.0, 8.0); //C++11之前只能用于固定尺寸的矩阵和向量,且尺寸不大于4

  • 如果启用 C++11,则可以通过传递任意数量的系数来初始化任意大小的固定大小的列或行向量:
Vector2i a(1, 2);                      // A column vector containing the elements {1, 2}
Matrix<int, 5, 1> b {
   
   1, 2, 3, 4, 5};   // A row-vector containing the elements {1, 2, 3, 4, 5}
Matrix<int, 1, 5> c = {
   
   1, 2, 3, 4, 5}; // A column vector containing the elements {1, 2, 3, 4, 5}
  • 无论是固定还是动态矩阵,系数必须按行分组:
MatrixXi a {
   
         // construct a 2x2 matrix
      {
   
   1, 2},     // first row
      {
   
   3, 4}      // second row
};
Matrix<double, 2, 3> b {
   
   
      {
   
   2, 3, 4},
      {
   
   5, 6, 7},
};
  • 但是对于列或行向量,允许隐式转置。这意味着可以用行向量初始化列向量:

    切记,只有向量才可以这样

VectorXd a {
   
   {
   
   1.5, 2.5, 3.5}};             // A column-vector with 3 coefficients
RowVectorXd b {
   
   {
   
   1.0, 2.0, 3.0, 4.0}};     // A row-vector with 4 coefficients

系数存取器

Eigen重载了圆括号()操作符,因此采用 (i,j) 取索引访问系数,对于向量只需要传递一个索引(i)即可,需要注意的是下标索引均是先行后列。

#include <iostream>
#include <Eigen/Dense>
 
using namespace Eigen;
 
int main()
{
   
   
  MatrixXd m(2,2);
  m(0,0) = 3;
  m(1,0) = 2.5;
  m(0,1) = -1;
  m(1,1) = m(1,0) + m(0,1);
  std::cout << "Here is the matrix m:\n" << m << std::endl;
  VectorXd v(2);
  v(0) = 4;
  v(1) = v(0) - 1
<think>好的,我现在需要解决用户在使用Eigen库时遇到的包含路径错误的问题。用户提到的错误是“Dense头文件报错”,具体路径是“D:/eigen-3.4.0/eigen-3.4.0/Eigen/Dense”。我需要结合用户提供的引用内容来找出解决方案。 首先,根据引用[3],安装Eigen库有两种方法:通过apt安装或者从官网下载源码。用户显然是从官网下载的,因为路径是D盘下的解压目录。引用[3]中提到,如果使用官网下载的源码,需要在项目的包含目录中添加Eigen的路径。例如在VS Studio中,右键项目属性,在VC++目录的包含目录里添加路径。用户可能没有正确设置这个路径,导致编译器找不到头文件。 然后看引用[1]和[2],其中提到需要将Eigen的路径包含到CMakeLists.txt中。比如,引用[2]中的CMakeLists.txt有include_directories("/home/joanna/Downloads/eigen-3.4.0"),这应该是用户项目中的Eigen路径。用户当前的路径是D:/eigen-3.4.0/eigen-3.4.0,可能需要检查CMakeLists中的路径是否正确,是否指向正确的Eigen父目录。 另外,引用[3]还提到可能需要将Eigen目录复制到系统的包含路径,比如/usr/local/include,但用户使用的是Windows系统(路径是D盘),所以可能需要不同的处理方式。在Windows下,通常是在IDE中设置包含路径,或者确保CMake正确配置。 用户可能在CMakeLists.txt中没有正确设置include_directories,或者路径写错了。例如,正确的路径应该是D:/eigen-3.4.0,而不是包含到Eigen子目录,因为Eigen的头文件位于解压后的目录中的Eigen文件夹。所以,如果include_directories指向的是D:/eigen-3.4.0,那么#include <Eigen/Dense>就能正确找到,因为Eigen目录在D:/eigen-3.4.0下。 另外,用户可能在代码中使用了错误的包含方式。例如,正确的方式是#include <Eigen/Dense>,但用户可能路径配置错误,导致编译器找不到这个路径。 还需要检查路径中的斜杠是否正确,Windows中使用反斜杠,但在CMake中可能需要用正斜杠或双反斜杠。例如,D:/eigen-3.4.0应该正确。 另外,引用[1]提到需要将Eigen的核心和Tensor部分复制到项目目录,但用户可能没有这样做,或者复制的位置不对。不过更常见的做法是直接在CMake中包含Eigen的根目录,而不需要复制文件到项目里。 可能的解决方案步骤: 1. 确认Eigen库的解压路径是否正确,路径是否存在。 2. 在CMakeLists.txt中使用include_directories命令添加Eigen的根目录,例如D:/eigen-3.4.03. 确保代码中的包含语句是#include <Eigen/Dense>。 4. 如果是使用Visual Studio,检查项目属性中的包含目录是否添加了Eigen的路径。 5. 重新生成CMake项目,并清理可能的缓存。 用户可能的问题在于CMakeLists.txt中的路径设置不正确,或者IDE的包含路径没有正确配置。需要指导用户检查这些配置,并确保路径正确无误。</think>### 解决Eigen库包含路径错误的步骤 #### 1. 确认Eigen库的安装路径 确保解压后的Eigen库路径为 `D:/eigen-3.4.0`,目录结构应包含 `Eigen` 子文件夹(如 `D:/eigen-3.4.0/Eigen`)。若解压后路径为 `D:/eigen-3.4.0/eigen-3.4.0`,需调整后续配置中的路径。 #### 2. 配置CMakeLists.txt 在项目的 `CMakeLists.txt` 中添加Eigen库的包含路径: ```cmake include_directories("D:/eigen-3.4.0") # 指向Eigen根目录,而非子文件夹 ``` 注意路径中无需包含 `Eigen` 子目录,因为头文件引用格式为 `#include <Eigen/Dense>`[^2][^3]。 #### 3. 验证Visual Studio配置(如适用) 如果使用Visual Studio: 1. 右键项目 → 属性 → **VC++目录** → **包含目录** → 添加路径 `D:/eigen-3.4.0`。 2. 清理项目并重新生成解决方案[^3]。 #### 4. 检查代码包含语句 确保代码中头文件引用格式正确: ```cpp #include <Eigen/Dense> // 正确格式 ``` 而非: ```cpp #include "D:/eigen-3.4.0/Eigen/Dense" // 错误格式 ``` #### 5. 重启开发环境 修改配置后,重启IDE或执行 `File → Reload CMake Project`(如CLion)以刷新路径缓存[^1]。 #### 6. 测试代码 使用简单代码验证安装: ```cpp #include <iostream> #include <Eigen/Dense> int main() { Eigen::MatrixXd m = Eigen::MatrixXd::Random(3,3); std::cout << m << std::endl; return 0; } ``` 若输出随机矩阵,则配置成功[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jacob-xyb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值