C++开源矩阵计算工具——Eigen的简单用法(二)

本文主要是Eigen中矩阵和向量的算术运算,在Eigen中的这些算术运算重载了C++的+,-,*,所以使用起来非常方便。

1、矩阵的运算

Eigen提供+、-、一元操作符“-”、+=、-=,例如:

二元操作符+/-表示两矩阵相加(矩阵中对应元素相加/,返回一个临时矩阵): B+C 或 B-C;

一元操作符-表示对矩阵取负(矩阵中对应元素取负,返回一个临时矩阵): -C; 

组合操作法+=或者-=表示(对应每隔元素都做相应操作):A += B 或者 A-=B

代码段1为矩阵的加减操作,代码如下:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << 1, 2,
3, 4;
MatrixXd b(2,2);
b << 2, 3,
1, 4;
std::cout << "a + b =\n" << a + b << std::endl;
std::cout << "a - b =\n" << a - b << std::endl;
std::cout << "Doing a += b;" << std::endl;
a += b;
std::cout << "Now a =\n" << a << std::endl;
Vector3d v(1,2,3);
Vector3d w(1,0,0);
std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}
输出结果为:

a + b =
3 5
4 8
a - b =
-1 -1
 2  0
Doing a += b;
Now a =
3 5
4 8
-v + w - v =
-1
-4
-6

另外,矩阵还提供与标量(单一个数字)的乘除操作,表示每个元素都与该标量进行乘除操作。例如:

二元操作符*在:A*a中表示矩阵A中的每隔元素都与数字a相乘,结果放在一个临时矩阵中,矩阵的值不会改变。

对于a*A、A/a、A*=a、A /=a也是一样,例如下面的代码:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << 1, 2,
3, 4;
Vector3d v(1,2,3);
std::cout << "a * 2.5 =\n" << a * 2.5 << std::endl;
std::cout << "0.1 * v =\n" << 0.1 * v << std::endl;
std::cout << "Doing v *= 2;" << std::endl;
v *= 2;
std::cout << "Now v =\n" << v << std::endl;
}
输出结果为:

a * 2.5 =
2.5  5
7.5 10
0.1 * v =
0.1
0.2
0.3
Doing v *= 2;
Now v =
2
4
6

需要注意:

在Eigen中,算术操作例如 “操作符+”并不会自己执行计算操作,他们只是返回一个“算术表达式对象”,而实际的计算则会延迟到后面的赋值时才进行。这些不影响你的使用,它只是为了方便Eigen的优化。

2、求矩阵的转置、共轭矩阵、伴随矩阵。

可以通过 成员函数transpose()conjugate(),和 adjoint()来完成,注意这些函数返回操作后的结果,而不会对原矩阵的元素进行直接操作,如果要让原矩阵的进行转换,则需要使用响应的InPlace函数,例如:transposeInPlace() 、 adjointInPlace() 之类。

例如下面的代码所示:

MatrixXcf a = MatrixXcf::Random(2,2);
cout << "Here is the matrix a\n" << a << endl;
cout << "Here is the matrix a^T\n" << a.transpose() << endl;
cout << "Here is the conjugate of a\n" << a.conjugate() << endl;
cout << "Here is the matrix a^*\n" << a.adjoint() << endl;
输出结果为:
Here is the matrix a
 (-0.211,0.68) (-0.605,0.823)
 (0.597,0.566)  (0.536,-0.33)
Here is the matrix a^T
(-0.211,0.68) (0.597,0.566)
(-0.605,0.823) (0.536,-0.33)
Here is the conjugate of a
 (-0.211,-0.68) (-0.605,-0.823)
 (0.597,-0.566)    (0.536,0.33)
Here is the matrix a^*
(-0.211,-0.68) (0.597,-0.566)
(-0.605,-0.823)   (0.536,0.33)


3、矩阵相乘、矩阵向量相乘

矩阵的相乘,矩阵与向量的相乘也是使用操作符*,共有*和*=两种操作符,其用法可以参考如下代码:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d mat;
mat << 1, 2,
3, 4;
Vector2d u(-1,1), v(2,0);
std::cout << "Here is mat*mat:\n" << mat*mat << std::endl;
std::cout << "Here is mat*u:\n" << mat*u << std::endl;
std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl;
std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl;
std::cout << "Let's multiply mat by itself" << std::endl;
mat = mat*mat;
std::cout << "Now mat is mat:\n" << mat << std::endl;
}
输出结果为:
Here is mat*mat:
 7 10
15 22
Here is mat*u:
1
1
Here is u^T*mat:
2 2
Here is u^T*v:
-2
Here is u*v^T:
-2 -0
 2  0
Let's multiply mat by itself
Now mat is mat:
 7 10
15 22


### C++ 中的矩阵运算方法及常用库 #### 使用标准容器实现基本矩阵运算 对于简单的应用场景,可以直接利用 `std::array` 或者 `std::vector` 来构建维数组表示矩阵,并通过循环结构手动编写加减乘除等基础运算法则。然而这种方式效率较低且容易出错,在实际项目尤其是高性能需求场景下并不推荐。 #### 借助第三方高效矩阵库 针对更复杂的应用场合以及追求性能优化的需求,则建议引入专门设计用来处理大规模数据集下的线性变换任务的专业级开源软件包: - **Eigen** Eigen 是一个基于模板元编程技术打造而成的高度灵活通用型C++数值计算框架之一[^1]。它不仅能够很好地兼容多种编译器环境而且具备出色的运行效能表现;更重要的是其API接口友好直观易于上手掌握。 下面给出一段创建两个随机初始化后的方阵A与B相乘得到结果矩阵C的例子: ```cpp #include <iostream> #include <Eigen/Dense> using namespace std; using namespace Eigen; int main() { MatrixXd A(3, 3), B(3, 3); // Fill matrices with random values between [-10; 10] A =MatrixXd ::Random(3, 3)*20 - MatrixXd::Ones(3, 3)*10; B =MatrixXd ::Random(3, 3)*20 - MatrixXd::Ones(3, 3)*10; cout << "Matrix A:\n" << A << endl; cout << "\nMatrix B:\n" << B << endl; MatrixXd C = A * B; cout << "\nThe product of matrix A and B is:\n\n"; cout << C << endl; return 0; } ``` - **Armadillo** Armadillo 提供了一套类似于MATLAB风格的语言特性来简化开发者的工作流程,特别适合那些习惯于脚本化快速原型验证的研究人员使用。该工具箱内部实现了众多经典算法模型可供调用,同时也允许用户自定义扩展新功能模块。 - **OpenCV (cv::Mat)** OpenCV 的核心组件 cv::Mat 类同样适用于执行各类图像处理相关的几何转换操作之外还能胜任常规意义上的张量分析工作[^2]。得益于内置多核处理器调度机制的支持,即使面对海量像素点也能保持流畅稳定的响应速度。 这里展示了一个简单的例子,展示了如何使用 OpenCV 创建和操作矩阵: ```cpp #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main(){ Mat m = Mat_<double>::ones(3,3); // Create a 3x3 double precision identity matrix cout<<"Initial matrix:"<<endl<<m<<endl; randu(m, Scalar::all(-1.), Scalar::all(1.)); // Generate uniformly distributed pseudorandom numbers within range (-1..1) cout<<"\nAfter generating pseudo-random elements:"<<endl<<m<<endl; return 0; } ``` - **ViennaCL** 如果目标平台拥有强大的图形硬件资源可资利用的话,那么不妨考虑尝试一下 ViennaCL —— 它专为加速科学工程仿真模拟而生的一站式解决方案提供商。凭借无缝对接 CUDA / OpenCL 编程接口的优势所在,能够在不影响原有业务逻辑的前提下轻松移植现有 CPU 版本代码至 GPU 上跑起来从而获得数量级上的提速增益效果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值