Eigen学习(四)Array类和元素级操作

Array类提供了和Matrix不同的操作,Matrix主要为了线性代数而设计,而Array类是通常用的数组。Array类提供了更方便的元素级的操作,但是没有线性代数方面的意义,比如给每个元素的值加上一个常数或按照元素相乘两个array对象。

Array

Array模板类的参数同Matrix类相同,前三个参数同样是

Array<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

剩余的三个参数也是可选的,因为和Matrix类的参数及作用完全相同,这里不做介绍了。

Eigen为Array对象同样提供了常用的类型的定义,由于array通常指的是一维或二维的数组,因此这些常用的定义和Matrix的稍有不同。ArrayNt表示一维的数组,N和t分别代表尺寸和数据类型。对于二维数组使用ArrayNNt定义,以下是一些例子

Array<float,Dynamic,1>
ArrayXf
Array<float,3,1>
Array3f
Array<double,Dynamic,Dynamic>
ArrayXXd
Array<double,3,3>
Array33d

访问Array内的数

和Matrix相同,圆括号运算符也被重载用来对数组的元素进行读和写。此外<<运算符也可以用于初始化数组或者输出数组。

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  ArrayXXf  m(2,2);
  
  // assign some values coefficient by coefficient
  m(0,0) = 1.0; m(0,1) = 2.0;
  m(1,0) = 3.0; m(1,1) = m(0,1) + m(1,0);
  
  // print values to standard output
  cout << m << endl << endl;
 
  // using the comma-initializer is also allowed
  m << 1.0,2.0,
       3.0,4.0;
     
  // print values to standard output
  cout << m << endl;
}

输出为

1 2
3 5

1 2
3 4

加减操作

对于数组的加减操作和Matrix相同,当数组尺寸相同时运算有效,并且加减运算是按照元素进行计算的。数组对象同样可以和一个标量进行相加,导致的结果是每个元素都和这个标量相加,这个功能是Matrix对象不具备的。

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  ArrayXXf a(3,3);
  ArrayXXf b(3,3);
  a << 1,2,3,
       4,5,6,
       7,8,9;
  b << 1,2,3,
       1,2,3,
       1,2,3;
       
  // Adding two arrays
  cout << "a + b = " << endl << a + b << endl << endl;
  // Subtracting a scalar from an array
  cout << "a - 2 = " << endl << a - 2 << endl;
}

输出为

a + b = 
 2  4  6
 5  7  9
 8 10 12

a - 2 = 
-1  0  1
 2  3  4
 5  6  7

数组乘运算

首先肯定可以用一个标量同数组相乘,这个和Matrix相同。不同的是当两个数组相乘时,执行的是对应的元素相乘,而Matrix相乘则是矩阵的积,因此只有两个数组尺寸相同时才能相乘。

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  ArrayXXf a(2,2);
  ArrayXXf b(2,2);
  a << 1,2,
       3,4;
  b << 5,6,
       7,8;
  cout << "a * b = " << endl << a * b << endl;
}

输出为

a * b = 
 5 12
21 32

其他的元素级操作

Array对象还有其他的一些操作,比如abs()方法返回数组每个元素的绝对值,sqrt()方法计算每个元素的根。如果你有两个尺寸相同的数组,可以使用min()方法构建一个新的数组,新的数组的元素是原来的两个数组的对应位置的最小值

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  ArrayXf a = ArrayXf::Random(5);
  a *= 2;
  cout << "a =" << endl 
       << a << endl;
  cout << "a.abs() =" << endl 
       << a.abs() << endl;
  cout << "a.abs().sqrt() =" << endl 
       << a.abs().sqrt() << endl;
  cout << "a.min(a.abs().sqrt()) =" << endl 
       << a.min(a.abs().sqrt()) << endl;
}

输出为

a =
  1.36
-0.422
  1.13
  1.19
  1.65
a.abs() =
 1.36
0.422
 1.13
 1.19
 1.65
a.abs().sqrt() =
1.17
0.65
1.06
1.09
1.28
a.min(a.abs().sqrt()) =
  1.17
-0.422
  1.06
  1.09
  1.28

Array和Matrix之间的转换

什么时候该使用矩阵?什么时候又使用数组?你不能对数组执行矩阵的运算,也不能对矩阵执行数组的运算。因此当你需要做线性代数的运算,比如矩阵乘积,那你应该使用矩阵。如果你要做元素级操作,你应该使用数组。然而有时事情并不那么容易,你可能需要同时使用数组和矩阵,这时候你就需要数组和矩阵之间的互相转换了。

矩阵对象有一个array()方法用于将矩阵表达成数组以便执行元素级操作。同样的Array对象也有一个matrix()方法。就像所有的Eigen抽象表示一样,这种转换并不耗费运行时间(编译器优化了),array()方法和matrix()方法即可用于左值也可用于右值。

Eigen中禁止将数组和矩阵混合在一个表达式中,比如不能直接将数组和矩阵相加。+运算符两侧必须都是矩阵或者数组。然而他们之间的互相转换很容易。这里的一个例外是=运算符:你可以将一个矩阵表达式赋值给一个数组对象,或者将一个数组表达式赋值给一个矩阵对象。

下面的例子介绍了上述方法的用法。比如,result = m.array()*n.array()将两个矩阵m和n转换成数组,然后执行元素级的相乘,最后将结果赋值给一个矩阵对象。

事实上Eign提供了一个cwiseProduct()方法进行矩阵间的元素级乘积。

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  MatrixXf m(2,2);
  MatrixXf n(2,2);
  MatrixXf result(2,2);
  m << 1,2,
       3,4;
  n << 5,6,
       7,8;
  result = m * n;
  cout << "-- Matrix m*n: --" << endl << result << endl << endl;
  result = m.array() * n.array();
  cout << "-- Array m*n: --" << endl << result << endl << endl;
  result = m.cwiseProduct(n);
  cout << "-- With cwiseProduct: --" << endl << result << endl << endl;
  result = m.array() + 4;
  cout << "-- Array m + 4: --" << endl << result << endl << endl;
}

输出为

-- Matrix m*n: --
19 22
43 50

-- Array m*n: --
 5 12
21 32

-- With cwiseProduct: --
 5 12
21 32

-- Array m + 4: --
5 6
7 8

类似的,如果array1和array2是数组,那么表达式array1.matrix()*array2.matrix()计算的是矩阵的积。

下面是一个进阶的例子。表达式(m.array()+4).matrix()*m将4加到m的每个元素上,然后计算结果和m的矩阵积。类似的,表达式(m.array()*n.array()).matrix()*m计算m和n的元素级乘积,之后再计算结果和m的矩阵积。

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  MatrixXf m(2,2);
  MatrixXf n(2,2);
  MatrixXf result(2,2);
  m << 1,2,
       3,4;
  n << 5,6,
       7,8;
  
  result = (m.array() + 4).matrix() * m;
  cout << "-- Combination 1: --" << endl << result << endl << endl;
  result = (m.array() * n.array()).matrix() * m;
  cout << "-- Combination 2: --" << endl << result << endl << endl;
}

输出

-- Combination 1: --
23 34
31 46

-- Combination 2: --
 41  58
117 170












  • 9
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值