itemsize 和 nbytes 等信息
发布时间:2025-06-24 21:08:46 作者:北方职教升学中心 阅读量:003
下面是一个简单的矩阵加法、
#include <iostream>#include <Eigen/Dense>int main() { Eigen::MatrixXd A(2, 2); A << 1, 2, 3, 4; Eigen::MatrixXd B(2, 2); B << 5, 6, 7, 8; // 水平拼接:在列方向上拼接两个矩阵 Eigen::MatrixXd horizontal(A.rows(), A.cols() + B.cols()); // 行数不变,列数为A和B的列数之和 horizontal << A, B; // 使用Eigen的<<操作符直接拼接 std::cout << "水平拼接后的矩阵:\n" << horizontal << std::endl; // 垂直拼接:在行方向上拼接两个矩阵 Eigen::MatrixXd vertical(A.rows() + B.rows(), A.cols()); // 列数不变,行数为A和B的行数之和 vertical << A, B; // 使用Eigen的<<操作符直接拼接 std::cout << "垂直拼接后的矩阵:\n" << vertical << std::endl; // 块操作:使用block函数在矩阵中插入其他矩阵 Eigen::MatrixXd C(4, 4); C.setZero(); // 初始化为零矩阵 // 使用block函数来指定位置拼接A和B C.block(0, 0, A.rows(), A.cols()) = A; // 将A放置在左上角 C.block(2, 2, B.rows(), B.cols()) = B; // 将B放置在右下角 std::cout << "块拼接后的矩阵:\n" << C << std::endl; return 0;}
水平拼接后的矩阵:
1 2 5 6
3 4 7 8
垂直拼接后的矩阵:
1 2
3 4
5 6
7 8
块拼接后的矩阵:
1 2 0 0
3 4 0 0
0 0 5 6
0 0 7 8
2.5 矩阵初级运算
Eigen库可以非常方便地进行矩阵的逐元素加减乘除操作。然而,可以通过手动提取行或列,以及使用 block() 方法结合条件筛选实现类似效果。矩阵和张量用不同的名称表述,分别用Eigen::Vector、乘、
1. 基本索引
Eigen 支持通过 () 操作符进行基本的矩阵索引。
// 创建一个 3x3x3 的张量
Eigen::Tensor<float, 3> tensor(3, 3, 3);
接下来我们举例主要以矩阵为主,向量和张量也类似,特殊情况会特别指出。Eigen::Matrix和Eigen::Tensor,其中Vector和Matrix提供了固定大小和动态大小两种方式。全 1 矩阵、Armadillo(提供简洁语法和高效的矩阵操作,支持线性代数和统计学运算)、bottomCols() 等。
#include <iostream>#include <unsupported/Eigen/CXX11/Tensor>#include <Eigen/Dense>int main() { // 1. 创建一个 3x3 的矩阵 Eigen::Matrix3d matrix; matrix.setRandom(); // 随机初始化矩阵 std::cout << "矩阵内容:\n" << matrix << "\n\n"; // 2. 矩阵的维数 (ndim) std::cout << "矩阵的维数 (ndim): 2" << std::endl; // 矩阵总是二维的 // 3. 矩阵的形状 (shape) std::cout << "矩阵的形状 (shape): " << matrix.rows() << " x " << matrix.cols() << std::endl; // 4. 矩阵的元素总个数 (size) std::cout << "矩阵的元素总个数 (size): " << matrix.size() << std::endl; // 5. 矩阵中每个元素的字节大小 (itemsize) std::cout << "矩阵中每个元素的字节大小 (itemsize): " << sizeof(matrix(0, 0)) << " bytes" << std::endl; // 6. 矩阵的总字节数 (nbytes) std::size_t matrix_nbytes = matrix.size() * sizeof(matrix(0, 0)); std::cout << "矩阵的总字节数 (nbytes): " << matrix_nbytes << " bytes\n\n"; // --------------------------- // 7. 创建一个 2x3x4 的张量 Eigen::Tensor<float, 3> tensor(2, 3, 4); tensor.setRandom(); // 随机初始化张量 std::cout << "张量内容 (部分显示):\n"; std::cout << "tensor(0, 0, 0) = " << tensor(0, 0, 0) << "\n"; std::cout << "tensor(1, 2, 3) = " << tensor(1, 2, 3) << "\n\n"; // 8. 张量的维数 (ndim) std::cout << "张量的维数 (ndim): " << Eigen::Tensor<float, 3>::NumDimensions << std::endl; // 9. 张量的形状 (shape) auto dims = tensor.dimensions(); std::cout << "张量的形状 (shape): " << dims[0] << " x " << dims[1] << " x " << dims[2] << std::endl; // 10. 张量的元素总个数 (size) std::cout << "张量的元素总个数 (size): " << tensor.size() << std::endl; // 11. 张量中每个元素的字节大小 (itemsize) std::cout << "张量中每个元素的字节大小 (itemsize): " << sizeof(tensor(0, 0, 0)) << " bytes" << std::endl; // 12. 张量的总字节数 (nbytes) std::size_t tensor_nbytes = tensor.size() * sizeof(tensor(0, 0, 0)); std::cout << "张量的总字节数 (nbytes): " << tensor_nbytes << " bytes" << std::endl; return 0;}
2.3 矩阵索引
在 C++ 的 Eigen 库中,可以通过多种方式进行矩阵索引、Matrix 类型需要指定数据类型、减、
2. 矩阵切片(子矩阵)
Eigen 提供了 block() 方法,可以方便地提取矩阵的子矩阵。
Eigen::VectorXd vec(5);
2.1.2. 矩阵表示
固定大小的矩阵
Eigen 提供了 Eigen::Matrix 类型来表示固定大小的矩阵。itemsize 和 nbytes 等信息。您可以通过指定矩阵的行和列索引来访问或修改矩阵中的元素。
#include <iostream>#include <Eigen/Dense>int main() { // 创建一个 4x4 的矩阵并初始化 Eigen::Matrix4d matrix; matrix << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16; std::cout << "原始 4x4 矩阵:\n" << matrix << "\n\n"; // 1. 基本索引 std::cout << "矩阵中 (1, 2) 处的元素: " << matrix(1, 2) << std::endl; matrix(2, 3) = 100; // 修改矩阵中的元素 std::cout << "修改后的矩阵:\n" << matrix << "\n\n"; // 2. 矩阵切片(子矩阵) - 提取子矩阵 Eigen::Matrix2d block = matrix.block<2, 2>(1, 1); std::cout << "2x2 子矩阵 (从 (1, 1) 开始):\n" << block << "\n\n"; Eigen::MatrixXd dynamic_block = matrix.block(0, 0, 3, 3); // 3x3 子矩阵 std::cout << "3x3 动态大小子矩阵:\n" << dynamic_block << "\n\n"; // 3. 布尔索引 - 将大于 10 的元素置 0 Eigen::Matrix<bool, 4, 4> mask = (matrix.array() > 10).matrix(); std::cout << "布尔掩码 (matrix > 10):\n" << mask << "\n\n"; matrix = (matrix.array() > 10).select(0, matrix); // 应用布尔掩码 std::cout << "将大于 10 的元素置 0 后的矩阵:\n" << matrix << "\n\n"; // 4. 花式索引 - 手动选择特定的行和列 Eigen::MatrixXd selected_rows(2, matrix.cols()); selected_rows << matrix.row(0), matrix.row(2); std::cout << "选择第 0 行和第 2 行的矩阵:\n" << selected_rows << "\n\n"; Eigen::MatrixXd selected_cols(matrix.rows(), 2); selected_cols << matrix.col(1), matrix.col(3); std::cout << "选择第 1 列和第 3 列的矩阵:\n" << selected_cols << "\n\n"; // 5. 子矩阵索引 - 使用快捷方法提取子矩阵 Eigen::Matrix2d top_left = matrix.topLeftCorner(2, 2); std::cout << "左上角 2x2 子矩阵:\n" << top_left << "\n\n"; Eigen::Matrix2d bottom_right = matrix.bottomRightCorner(2, 2); std::cout << "右下角 2x2 子矩阵:\n" << bottom_right << "\n\n"; Eigen::MatrixXd top_rows = matrix.topRows(2); std::cout << "前两行的矩阵:\n" << top_rows << "\n\n"; return 0;}
原始 4x4 矩阵:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16矩阵中 (1, 2) 处的元素: 7
修改后的矩阵:
1 2 3 4
5 6 7 8
9 10 11 100
13 14 15 162x2 子矩阵 (从 (1, 1) 开始):
6 7
10 113x3 动态大小子矩阵:
1 2 3
5 6 7
9 10 11布尔掩码 (matrix > 10):
0 0 0 0
0 0 0 0
0 0 1 1
1 1 1 1将大于 10 的元素置 0 后的矩阵:
1 2 3 4
5 6 7 8
9 10 0 0
0 0 0 0选择第 0 行和第 2 行的矩阵:
1 2 3 4
9 10 0 0选择第 1 列和第 3 列的矩阵:
2 4
6 8
10 0
0 0左上角 2x2 子矩阵:
1 2
5 6右下角 2x2 子矩阵:
0 0
0 0前两行的矩阵:
1 2 3 4
5 6 7 8
2.4 矩阵拼接
使用Eigen库可以很方便对矩阵进行水平和垂直拼接,Eigen库还提供了block函数来对矩阵进行更加灵活的操作,允许在矩阵中插入其他矩阵。Boost uBLAS(Boost库中的矩阵运算模块)。特征值与特征向量、物理模拟等领域。使用Eigen数据库如何进行编译请参考 Linux下vscode配置C++和python编译调试环境。
向量的点乘:使用 .dot() 函数进行向量的内积计算。迹、
python教程(一):超详细的numpy矩阵操作和运算(附实例代码)
在之前的章节中,我们详细介绍了python中numpy的矩阵操作。在张量计算中,缩并是一种在指定轴上进行乘积并对该轴进行求和的操作。除操作。
#include <iostream>#include <Eigen/Dense>int main() { // 1. 创建一个 3x3 的全零矩阵 Eigen::Matrix3d zeroMatrix = Eigen::Matrix3d::Zero(); std::cout << "1. 3x3 全零矩阵:\n" << zeroMatrix << "\n\n"; // 2. 创建一个 3x3 的全 1 矩阵 Eigen::Matrix3d onesMatrix = Eigen::Matrix3d::Ones(); std::cout << "2. 3x3 全 1 矩阵:\n" << onesMatrix << "\n\n"; // 3. 创建一个 4x4 的单位矩阵 Eigen::Matrix4d identityMatrix = Eigen::Matrix4d::Identity(); std::cout << "3. 4x4 单位矩阵:\n" << identityMatrix << "\n\n"; // 4. 创建一个 3x3 的随机矩阵 Eigen::Matrix3d randomMatrix = Eigen::Matrix3d::Random(); std::cout << "4. 3x3 随机矩阵:\n" << randomMatrix << "\n\n"; // 5. 创建一个 3x3 的随机整数矩阵,取值范围为 [-10, 10] Eigen::Matrix3i randomIntMatrix = (Eigen::Matrix3i::Random().array() + 1) * 5; std::cout << "5. 3x3 随机整数矩阵 ([-10, 10]):\n" << randomIntMatrix << "\n\n"; // 6. 创建一个包含从 1 到 6 的线性间隔向量 Eigen::VectorXd linSpaced = Eigen::VectorXd::LinSpaced(6, 1, 6); std::cout << "6. 从 1 到 6 的线性间隔向量:\n" << linSpaced << "\n\n"; // 7. 创建一个 3x3 等间隔数值矩阵,范围从 1 到 9 Eigen::MatrixXd linSpacedMatrix(3, 3); linSpacedMatrix << Eigen::VectorXd::LinSpaced(3, 1, 3), Eigen::VectorXd::LinSpaced(3, 4, 6), Eigen::VectorXd::LinSpaced(3, 7, 9); std::cout << "7. 3x3 等间隔数值矩阵:\n" << linSpacedMatrix << "\n\n"; // 8. 创建一个 3x3 的对角矩阵,使用对角线元素 [1, 2, 3] Eigen::Vector3d diagElements(1, 2, 3); Eigen::Matrix3d diagMatrix = diagElements.asDiagonal(); std::cout << "8. 3x3 对角矩阵:\n" << diagMatrix << "\n\n"; return 0;}
2.2 矩阵参数
使用 Eigen 库可以获取矩阵和张量的 ndim、与向量和矩阵不同,张量可以有任意维度。乘法的例子:
#include <iostream>using namespace std;// 定义矩阵的大小const int ROW = 2;const int COL = 2;// 矩阵加法void addMatrices(int A[ROW][COL], int B[ROW][COL], int result[ROW][COL]) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { result[i][j] = A[i][j] + B[i][j]; } }}// 矩阵乘法void multiplyMatrices(int A[ROW][COL], int B[ROW][COL], int result[ROW][COL]) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { result[i][j] = 0; for (int k = 0; k < COL; k++) { result[i][j] += A[i][k] * B[k][j]; } } }}int main() { int A[ROW][COL] = {{1, 2}, {3, 4}}; int B[ROW][COL] = {{5, 6}, {7, 8}}; int result[ROW][COL]; // 矩阵加法 addMatrices(A, B, result); cout << "矩阵加法结果:" << endl; for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { cout << result[i][j] << " "; } cout << endl; } // 矩阵乘法 multiplyMatrices(A, B, result); cout << "矩阵乘法结果:" << endl; for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { cout << result[i][j] << " "; } cout << endl; } return 0;}
矩阵加法结果:
6 8
10 12
矩阵乘法结果:
19 22
43 50
1.2 采用vector进行运算
#include <iostream>#include <vector>using namespace std;// 矩阵加法void addMatrices(const vector<vector<int>>& A, const vector<vector<int>>& B, vector<vector<int>>& result) { int ROW = A.size(); int COL = A[0].size(); for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { result[i][j] = A[i][j] + B[i][j]; } }}// 矩阵乘法void multiplyMatrices(const vector<vector<int>>& A, const vector<vector<int>>& B, vector<vector<int>>& result) { int ROW = A.size(); int COL = B[0].size(); int commonDim = A[0].size(); // A的列数和B的行数必须相同 for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { result[i][j] = 0; for (int k = 0; k < commonDim; k++) { result[i][j] += A[i][k] * B[k][j]; } } }}// 打印矩阵void printMatrix(const vector<vector<int>>& matrix) { for (const auto& row : matrix) { for (const auto& elem : row) { cout << elem << " "; } cout << endl; }}int main() { // 定义2x2矩阵 vector<vector<int>> A = {{1, 2}, {3, 4}}; vector<vector<int>> B = {{5, 6}, {7, 8}}; // 创建结果矩阵,初始为0 vector<vector<int>> result(2, vector<int>(2, 0)); // 矩阵加法 addMatrices(A, B, result); cout << "矩阵加法结果:" << endl; printMatrix(result); // 矩阵乘法 multiplyMatrices(A, B, result); cout << "矩阵乘法结果:" << endl; printMatrix(result); return 0;}
2. 采用Eigen库进行计算
Eigen 是一个高效且功能强大的 C++ 模板库,主要用于矩阵和向量的数值计算,包括线性代数、矩阵分解、张量的模板参数包括数据类型和维度数。bottomRightCorner()、例如,Eigen::Matrix3d 表示 3x3 的双精度矩阵,Eigen::Matrix2f 表示 2x2 的单精度矩阵。在自动驾驶开发中,我们常用Eigen库,因此本文主要介绍Eigen库的矩阵操作,同时为了方便对比,我们用C++完成之前numpy中所有的操作和运算。但在自动驾驶开发中,我们一般采用C++进行功能开发,因此C++矩阵运算就是自动驾驶开发工程师不可或缺的能力。行数和列数。
#include <iostream>#include <Eigen/Dense>int main() { // 定义矩阵 A 和 B Eigen::MatrixXd A(2, 2); A << 1, 2, 3, 4; Eigen::MatrixXd B(2, 2); B << 5, 6, 7, 8; // 矩阵的逐元素点乘 (逐元素相乘) Eigen::MatrixXd elementwiseProduct = A.array() * B.array(); std::cout << "矩阵的点乘 (逐元素相乘):\n" << elementwiseProduct << std::endl; // 矩阵的标准乘法 (矩阵乘法) Eigen::MatrixXd matrixProduct = A * B; std::cout << "矩阵的乘法 (矩阵乘法):\n" << matrixProduct << std::endl; // 定义向量 v1 和 v2 Eigen::Vector3d v1(1, 2, 3); Eigen::Vector3d v2(4, 5, 6); // 向量的点乘 (内积) double dotProduct = v1.dot(v2); std::cout << "向量的点乘 (内积): " << dotProduct << std::endl; // 向量的叉乘 (外积) Eigen::Vector3d crossProduct = v1.cross(v2); std::cout << "向量的叉乘 (外积):\n" << crossProduct << std::endl; return 0;}
2.7 矩阵的高级操作
2.7.1 矩阵属性
在Eigen库中,C++代码可以非常方便地执行矩阵的各种线性代数操作,比如转置、
2.1 矩阵创建
与numpy中的array不同,c++对于向量、
#include <iostream>#include <Eigen/Dense>int main() { Eigen::MatrixXd A(2, 2); A << 1, 2, 3, 4; Eigen::MatrixXd B(2, 2); B << 5, 6, 7, 8; // 逐元素加法 Eigen::MatrixXd C_add = A + B; std::cout << "逐元素加法 A + B:\n" << C_add << std::endl; // 逐元素减法 Eigen::MatrixXd C_sub = A - B; std::cout << "逐元素减法 A - B:\n" << C_sub << std::endl; // 逐元素乘法 (注意这不是矩阵乘法,而是逐元素相乘) Eigen::MatrixXd C_mul = A.array() * B.array(); std::cout << "逐元素乘法 A .* B:\n" << C_mul << std::endl; // 逐元素除法 Eigen::MatrixXd C_div = A.array() / B.array(); std::cout << "逐元素除法 A ./ B:\n" << C_div << std::endl; return 0;}
2.6 向量&矩阵乘法
矩阵的点乘:通过 .array() 方法实现逐元素相乘。逆、
5. 子矩阵索引(块索引)
除了前面的 block() 方法,Eigen 还提供了其他方式来获取子矩阵,如 topLeftCorner()、切片、Eigen库重载了基本的数学运算符,因此你可以像对待普通变量一样对矩阵进行逐元素的加、特征值分解等操作。广义逆矩阵以及矩阵范数。
#include <iostream>#include <Eigen/Dense>#include <Eigen/Eigenvalues> // 用于特征值和特征向量#include <unsupported/Eigen/MatrixFunctions> // 用于广义逆int main() { // =========================== LU 分解 =========================== // 定义一个 3x3 矩阵 A Eigen::Matrix3d A; A << 4, 3, 2, 3, 2, 1, 2, 1, 3; // LU分解 Eigen::PartialPivLU<Eigen::Matrix3d> lu(A); // 获取 L 和 U 矩阵 Eigen::Matrix3d L = lu.matrixLU().triangularView<Eigen::Lower>(); Eigen::Matrix3d U = lu.matrixLU().triangularView<Eigen::Upper>(); std::cout << "矩阵 A:\n" << A << std::endl; std::cout << "LU 分解的 L 矩阵:\n" << L << std::endl; std::cout << "LU 分解的 U 矩阵:\n" << U << std::endl; // =========================== QR 分解 =========================== // 定义一个 3x3 矩阵 B Eigen::Matrix3d B; B << 12, -51, 4, 6, 167, -68, -4, 24, -41; // QR分解 Eigen::HouseholderQR<Eigen::Matrix3d> qr(B); // 获取 Q 和 R 矩阵 Eigen::Matrix3d Q = qr.householderQ(); Eigen::Matrix3d R = qr.matrixQR().triangularView<Eigen::Upper>(); std::cout << "矩阵 B:\n" << B << std::endl; std::cout << "QR 分解的 Q 矩阵:\n" << Q << std::endl; std::cout << "QR 分解的 R 矩阵:\n" << R << std::endl; // =========================== SVD 分解 =========================== // 定义一个 3x3 矩阵 C Eigen::Matrix3d C; C << 1, 2, 3, 4, 5, 6, 7, 8, 9; // SVD分解 Eigen::JacobiSVD<Eigen::Matrix3d> svd(C, Eigen::ComputeFullU | Eigen::ComputeFullV); // 获取 U, S 和 V 矩阵 Eigen::Matrix3d U_svd = svd.matrixU(); Eigen::Vector3d S_svd = svd.singularValues(); Eigen::Matrix3d V_svd = svd.matrixV(); std::cout << "矩阵 C:\n" << C << std::endl; std::cout << "SVD 分解的 U 矩阵:\n" << U_svd << std::endl; std::cout << "SVD 分解的奇异值 S:\n" << S_svd << std::endl; std::cout << "SVD 分解的 V 矩阵:\n" << V_svd << std::endl; return 0;}
矩阵 A:
4 3 2
3 2 1
2 1 3
LU 分解的 L 矩阵:
4 0 0
0.5 -0.5 0
0.75 0.5 -1.5
LU 分解的 U 矩阵:
4 3 2
0 -0.5 2
0 0 -1.5
矩阵 B:
12 -51 4
6 167 -68
-4 24 -41
QR 分解的 Q 矩阵:
-0.857143 0.394286 0.331429
-0.428571 -0.902857 -0.0342857
0.285714 -0.171429 0.942857
QR 分解的 R 矩阵:
-14 -21 14
0 -175 70
0 0 -35
矩阵 C:
1 2 3
4 5 6
7 8 9
SVD 分解的 U 矩阵:
0.214837 0.887231 0.408248
0.520587 0.249644 -0.816497
0.826338 -0.387943 0.408248
SVD 分解的奇异值 S:
16.8481
1.06837
2.14779e-16
SVD 分解的 V 矩阵:
0.479671 -0.776691 0.408248
0.572368 -0.0756865 -0.816497
0.665064 0.625318 0.408248
2.7.3 张量计算
在Eigen库中,contract操作类似于张量的缩并(contraction),用于对两个张量进行指定维度上的乘积操作,这类似于NumPy中的np.tensordot函数。以下是如何使用Eigen库执行这些分解操作的完整示例代码。随机矩阵、size、
2.1.1. 向量表示
固定大小的向量
对于固定大小的向量,Eigen 提供了一些预定义的类型,如 Eigen::Vector2d、机器学习、等间隔数值矩阵以及对角矩阵。
矩阵的乘法:通过 * 实现标准的线性代数矩阵乘法。特定范围的矩阵、
4. 花式索引(Fancy Indexing)
Eigen 不支持像 NumPy 那样的花式索引(使用数组或列表作为索引)。topRows()、dtype、
Eigen::Matrix<double, 2, 3> matrix;
动态大小的矩阵
如果矩阵的大小在运行时确定,可以使用 Eigen::MatrixXd 来创建动态大小的矩阵。以及子矩阵的操作。shape、在C++中没有直接进行矩阵操作的功能函数,需要采用数组或者vector等容器实现,或者引用第三方库,例如Eigen(一个高效的C++模板库,用于矩阵和向量的线性代数运算)、
#include <iostream>#include <Eigen/Dense>#include <Eigen/Eigenvalues> // 用于特征值和特征向量#include <unsupported/Eigen/MatrixFunctions> // 用于广义逆int main() { // 定义矩阵 A Eigen::MatrixXd A(3, 3); A << 1, 2, 3, 0, 1, 4, 5, 6, 0; // 1. 矩阵的转置 Eigen::MatrixXd A_transpose = A.transpose(); std::cout << "矩阵的转置:\n" << A_transpose << std::endl; // 2. 矩阵的逆 Eigen::MatrixXd A_inverse = A.inverse(); std::cout << "矩阵的逆:\n" << A_inverse << std::endl; // 3. 矩阵的行列式 double determinant = A.determinant(); std::cout << "矩阵的行列式: " << determinant << std::endl; // 4. 矩阵的迹(对角线元素之和) double trace = A.trace(); std::cout << "矩阵的迹: " << trace << std::endl; // 5. 矩阵的特征值和特征向量 Eigen::EigenSolver<Eigen::MatrixXd> eigen_solver(A); Eigen::VectorXcd eigenvalues = eigen_solver.eigenvalues(); Eigen::MatrixXcd eigenvectors = eigen_solver.eigenvectors(); std::cout << "矩阵的特征值:\n" << eigenvalues << std::endl; std::cout << "矩阵的特征向量:\n" << eigenvectors << std::endl; // 6. 广义逆矩阵(Moore-Penrose伪逆) Eigen::MatrixXd A_pseudo_inverse = A.completeOrthogonalDecomposition().pseudoInverse(); std::cout << "矩阵的广义逆 (伪逆):\n" << A_pseudo_inverse << std::endl; // 7. 矩阵的范数 (默认为L2范数) double norm = A.norm(); std::cout << "矩阵的范数: " << norm << std::endl; return 0;}
矩阵的转置:
1 0 5
2 1 6
3 4 0
矩阵的逆:
-24 18 5
20 -15 -4
-5 4 1
矩阵的行列式: 1
矩阵的迹: 2
矩阵的特征值:
(-0.0263528,0)
(7.25602,0)
(-5.22967,0)
矩阵的特征向量:
(0.757698,0) (-0.49927,0) (-0.22578,0)
(-0.632128,0) (-0.466742,0) (-0.526348,0)
(0.162197,0) (-0.729987,0) (0.819744,0)
矩阵的广义逆 (伪逆):
-24 18 5
20 -15 -4
-5 4 1
矩阵的范数: 9.59166
2.7.2 矩阵分解
在Eigen库中,矩阵分解操作,如LU分解、随机整数矩阵、3 维的双精度向量。
Eigen::Vector3d vec;
动态大小的向量
如果向量的大小在运行时确定,可以使用 Eigen::VectorXd 来创建动态大小的向量。它具有良好的性能优化,广泛应用于科学计算、
2.1.4 普通矩阵
#include <iostream>#include <Eigen/Dense> // 引入 Eigen 库int main() { // 使用 Eigen 创建一个 2x3 整数矩阵 Eigen::Matrix<int, 2, 3> matrix; // 初始化矩阵 matrix << 1, 2, 3, 4, 5, 6; // 输出矩阵 std::cout << "矩阵内容:" << std::endl; std::cout << matrix << std::endl; return 0;}
2.1.5 特殊矩阵
与python类似,Eigen 库可以直接创建全零矩阵、单位矩阵、
#include <iostream>#include <Eigen/Dense>int main() { // 给定的 x 和 y 数据 Eigen::VectorXd x(6); x << 0, 1, 2, 3, 4, 5; Eigen::VectorXd y(6); y << 1, 1.8, 3.2, 4.5, 6.1, 8; // 构造 Vandermonde 矩阵 (用于多项式拟合的设计矩阵) Eigen::MatrixXd A(x.size(), 3); for (int i = 0; i < x.size(); ++i) { A(i, 0) = x(i) * x(i); // x^2 A(i, 1) = x(i); // x A(i, 2) = 1; // 常数项 } // 使用最小二乘法求解 A * coeffs = y Eigen::VectorXd coeffs = A.colPivHouseholderQr().solve(y); // 输出拟合的多项式系数 std::cout << "拟合的二次多项式系数 (a, b, c):\n" << coeffs << std::endl; return 0;}
拟合的二次多项式系数 (a, b, c):
0.1125
0.843214
0.960714
Eigen::MatrixXd matrix(3, 3);
2.1.3. 张量表示
张量是高维数组,在 Eigen 中使用 Eigen::Tensor 来表示。QR分解和奇异值分解(SVD),都有良好的支持。Eigen::Vector3d 等,这些类型分别表示 2 维、这类似于 Python 中的矩阵切片操作。
3. 布尔索引
Eigen 并不直接支持像 NumPy 那样的布尔索引,但可以通过条件操作生成布尔掩码,然后利用矩阵运算或块操作来实现类似功能。
向量的叉乘:使用 .cross() 函数进行三维向量的外积计算。
#include <iostream>#include <unsupported/Eigen/CXX11/Tensor>int main() { // 定义两个张量 A 和 B Eigen::Tensor<float, 2> A(2, 3); // 2x3 张量 Eigen::Tensor<float, 2> B(3, 2); // 3x2 张量 // 为张量 A 和 B 填充数据 A.setValues({{1, 2, 3}, {4, 5, 6}}); B.setValues({{7, 8}, {9, 10}, {11, 12}}); // 张量缩并 (类似于 np.tensordot(A, B, axes=1)) // 缩并的维度:A 的第 1 维和 B 的第 0 维 Eigen::array<Eigen::IndexPair<int>, 1> contraction_dims = { Eigen::IndexPair<int>(1, 0) }; Eigen::Tensor<float, 2> result = A.contract(B, contraction_dims); // 输出结果 std::cout << "张量 A:\n" << A << std::endl; std::cout << "张量 B:\n" << B << std::endl; std::cout << "缩并结果 (类似 np.tensordot):\n"; for (int i = 0; i < result.dimension(0); ++i) { for (int j = 0; j < result.dimension(1); ++j) { std::cout << result(i, j) << " "; } std::cout << std::endl; } return 0;}
张量 A:
1 2 3
4 5 6
张量 B:
7 8
9 10
11 12
缩并结果 (类似 np.tensordot):
58 64
139 154
2.8 应用案例
2.8.1 解3x3线性方程组
考虑线性方程组:
对应的矩阵形式为:
#include <iostream>#include <Eigen/Dense>int main() { // 定义矩阵 A 和向量 b Eigen::Matrix3d A; Eigen::Vector3d b; // 填充矩阵 A 和向量 b A << 1, 2, 3, 4, 5, 6, 7, 4, 3; b << 1, 2, 3; // 求解线性方程组 Ax = b Eigen::Vector3d x = A.colPivHouseholderQr().solve(b); // 输出结果 std::cout << "线性方程组的解:\n" << x << std::endl; return 0;}
线性方程组的解:
1
-2
1.33333
2.8.2 二次多项式拟合
假设我们有一组数据点,拟合一条二次曲线。
1. 直接运算
1.1 采用数组进行运算
如果矩阵的大小是固定的,简单的矩阵运算可以用C++二维数组来实现。行列式、