数组(The Array class)
数组是比较通用的类,不像矩阵专注于线性代数。
此外,Array类提供了一种简单的方法来执行系数操作,这可能没有线性代数含义,例如向数组中的每个系数添加一个常数或将两个数组按系数相乘。
数组类型
Array是一个类模板,它采用与Matrix相同的模板参数。与Matrix 一样,前三个模板参数是必需的:
Array<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
后面三个参数和矩阵类完全相同,详情请参考 矩阵类
Eigen还为一些常见情况提供了 typedef,其方式类似于Matrix typedef,但有一些细微差别,因为“数组”一词用于一维和二维数组。
Eigen采用这样的约定,即 ArrayNt 形式的 typedef 代表一维数组,其中 N 和 t 是大小和标量类型,如本页中解释的矩阵typedef所示。对于二维数组,我们使用 ArrayNNt 形式的 typedef。
示例:
Type | Typedef |
---|---|
Array<float,Dynamic,1> | ArrayXf |
Array<float,3,1> | Array3f |
Array<double,Dynamic,Dynamic> | ArrayXXd |
Array<double,3,3> | Array33d |
访问数组
Eigen重载了括号运算符访问数组。
同时,左移运算符也被重载用于(逗号)初始化,和打印输出。
void Eigen_Introduction_ArrayClass_001()
{
ArrayXXf a(2, 2);
ArrayXXf b(2, 2);
a(0, 0) = 1; a(0, 1) = 2;
a(1, 0) = 3; a(1, 1) = 4;
cout << "a\n" << a << endl;
b << 4, 3, 2, 1;
cout << "b\n" << b << endl;
}
输出:
a
1 2
3 4
b
4 3
2 1
四则运算
- 加减运算
两个数组的加减与矩阵相同。如果两个数组具有相同的大小,并且加法或减法是按系数进行的,则该操作是有效的。
数组还支持 array + scalar
将标量添加到数组中的每个系数的形式的表达式。(这提供了不能直接用于Matrix对象的功能)
- 乘除运算
首先,array * scalar
数组乘标量的运算当然是可行的,与矩阵完全一致。
但是!!!,array*array
与 matrix*matrix
是不一样的:
矩阵相乘的结果为矩阵乘积;(m,n)*(n,p)=(m,p)
数组相乘的结果为系数乘积;(m,n)*(m,n)=(m,n)
//Array四则运算
void Eigen_Introduction_ArrayClass_002()
{
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;
cout << "a + b = " << endl << a + b << endl;
cout << "a - 2 = " << endl << a - 2 << endl;
cout << "a * b = " << endl << a * b << endl;
cout << "a / b = " << endl << a / b << endl;
}
输出:
a + b =
2 4 6
5 7 9
8 10 12
a - 2 =
-1 0 1
2 3 4
5 6 7
a * b =
1 4 9
4 10 18
7 16 27
a / b =
1 1 1
4 2.5 2
7 4 3
其他函数操作
.abs()
、.sqrt()
等等,
.min(.)
返回两个同规模数组对应系数最小值的新数组。
//Array其他函数操作
void Eigen_Introduction_ArrayClass_003()
{
ArrayXf a = ArrayXf::Random(5);
ArrayXf b = ArrayXf::Random(5);
cout << "a = " << endl
<< a.transpose() << endl;
cout << "b = " << endl
<< b.transpose() << endl;
cout << "a.abs() = " << endl
<< a.abs().transpose() << endl; //绝对值
cout << "a.sqrt() =" << endl
<< a.abs().sqrt().transpose() << endl; //开方
cout << "a.minCoeff() = " << endl
<< a.minCoeff() << endl; //最小系数
cout << "a.maxCoeff() = " << endl
<< a.maxCoeff() << endl; //最大系数
cout << "a.min(b)" << endl
<< a.min(b).transpose() << endl; //对应最小值
cout << "a.max(b)" << endl
<< a.max(b).transpose() << endl; //对应最大值
}
输出:
a =
-0.113254 -0.110202 0.632496 -0.0588702 -0.971007
b =
0.851558 0.741935 0.148534 0.241005 -0.610828
a.abs() =
0.113254 0.110202 0.632496 0.0588702 0.971007
a.sqrt() =
0.336533 0.331967 0.795296 0.242632 0.985397
a.minCoeff() =
-0.971007
a.maxCoeff() =
0.632496
a.min(b)
-0.113254 -0.110202 0.148534 -0.0588702 -0.971007
a.max(b)
0.851558 0.741935 0.632496 0.241005 -0.610828
数组和矩阵相互转换
线性代数运算时需要用矩阵类,系数运算时需要用数组类;但是往往需要两种类型交替使用。
所以数组和矩阵的相互转换就显得尤为重要了,.array()
和 .matrix()
就出现了。
Eigen禁止在表达式中混合矩阵和数组。例如,您不能直接添加矩阵和数组;运算+符的操作数要么都是矩阵,要么都是数组。但是,使用.array()和.matrix()很容易从一种转换到另一种。
这条规则的例外是赋值运算符:允许将矩阵表达式赋值给数组变量,或将数组表达式赋值给矩阵变量。
因此两个同尺寸的矩阵转换成数组相乘再分配给矩阵的语法也是合法的:result = m1.array()*m2.array()
事实上,这种用法非常普遍,以至于Eigen为矩阵提供了一个const .cwiseProduct(.)方法来计算系数乘积。
/* Matrix to Array*/
void Eigen_Introduction_ArrayClass_004()
{
Matrix2f m1, m2;
Matrix2f result;
Array22f a1, a2;
m1 << 1, 2,
3, 4;
m2 << 2, 2,
2, 2;
result = m1 * m2;
cout << "-- Matrix m*n: --" << endl << result << endl << endl;
result = m1.array() * m2.array();
cout << "-- Array m*n: --" << endl << result << endl << endl;
result = m1.cwiseProduct(m2);
cout << "-- With cwiseProduct: --" << endl << result << endl << endl;
result = m1.array() + 4;
cout << "-- Array m + 4: --" << endl << result << endl << endl;
}
/* Array to Matrix*/
void Eigen_Introduction_ArrayClass_005()
{
//主要测一下矩阵怎么执行数组运算
Matrix2f m1, m2;
Matrix2f result;
m1 << 1, 2,
3, 4;
m2 << 2, 2,
2, 2;
result = (m1.array() + 4).matrix() * m2;
cout << "-- Combination 1: --" << endl << result << endl << endl;
result = (m1.array() * m2.array()).matrix() * m2;
cout << "-- Combination 2: --" << endl << result << endl << endl;
}
输出
/* Matrix to Array*/
-- Matrix m*n: --
6 6
14 14
-- Array m*n: --
2 4
6 8
-- With cwiseProduct: --
2 4
6 8
-- Array m + 4: --
5 6
7 8
/* Array to Matrix*/
-- Combination 1: --
22 22
30 30
-- Combination 2: --
12 12
28 28