C++ 的 Eigen 类库学习

一、Eigen 是什么

Eigen 是一个 C++ 中的用于科学计算(矩阵)的类库,提供了非常方便的接口,最近我们小组需要做一个项目,里面涉及到很多的矩阵的计算,于是我打算使用这个类库结合我的 CLion 写代码

二、如何配置

下载最新的 release 安装包 解压到项目的目录下(当然任何目录都可以,我习惯上解压到项目的目录下,这样比较方便管理),然后我们配置我们的 CMakeLists.txt

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(juzhen)

set(CMAKE_CXX_STANDARD 11)


include_directories(../eigen)//这里写你的解压目录


add_executable(juzhen main.cpp)

main.cpp

#include <iostream>
#include <Eigen/Dense>

using namespace Eigen;
using namespace std;

int main() {
    typedef Matrix<int,3,3> hh;
    MatrixXd m = MatrixXd::Random(3,3);
    //m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
    MatrixXd c = MatrixXd::Constant(3,3,1)*10;
    hh x;
    cout << "m =" << endl << m << endl;
    cout << "c =" << endl << c << endl;
    cout << "x =" << endl << x << endl;
}

这样就能运行啦

三、Eigen 基础

1.Matrix 类

1.基本:

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

Matrix的三个必需模板参数是:

Matrix <typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime>

例如: Matrix4f是浮动的4x4矩阵

typedef Matrix <float,4,4> Matrix4f ;

假如:我想生成一个 int 型的 3x3 的矩阵

示例代码:

#include <iostream>
#include <Eigen/Dense>

using namespace Eigen;
using namespace std;

int main() {
    typedef Matrix<int,3,3> hh;
    hh x;
    cout << "x =" << endl << x << endl;
}

结果:

x =
2001839094         36          0
2001791111    6880932 1275664310
        -1          4    6880948

2.向量

向量只是一种特殊的矩阵而已

列向量:

typedef Matrix <float,3,1> Vector3f ;

行向量:

typedef Matrix <int,1,2> RowVector2i ;

3.动态值

我们当然不满足在编译时就确定矩阵的大小,于是他给我们也提供了对应的方法

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

typedef Matrix <double,Dynamic,Dynamic> MatrixXd ;

同样,我们定义了一个不言自明的typedef VectorXi如下:

typedef Matrix <int,Dynamic,1> VectorXi ;

您可以完美地拥有例如具有动态列数的固定行数,如下所示:

Matrix <float,3,Dynamic>

4.构造函数

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

Matrix3f a;
MatrixXf b;

a 是一个3乘3的矩阵,具有未初始化系数的普通浮点数
b 是一个动态大小的矩阵,其大小目前是0乘0,并且其系数数组尚未分配。

注意:

Matrix3i d;

这里代表声明了一个 Int 型的 3x3 的矩阵,也就是说 最后的f 代表的是 float

对于矩阵,始终首先传递行数。对于矢量,只需传递矢量大小。它们使用给定的大小分配系数数组,但不自行初始化系数:

MatrixXf a(10,15);
VectorXf b(30);

a 是一个10x15动态大小的矩阵,具有已分配但当前未初始化的系数。
b 是一个大小为30的动态大小向量,具有已分配但当前未初始化的系数

注意:

RowVector2d e(1.0,2.0);

这个代表生成的是一个行向量(不加 row 是列向量)

5.系数访问器

示例代码:

#include <iostream>
#include <Eigen/Dense>

using namespace Eigen;
using namespace std;

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 << "这是矩阵m:\n" << m << std :: endl;

    VectorXd v(2);
    v(0)= 4;
    v(1)= v(0) - 1;
    std :: cout << "这是向量v:\n" << v << std :: endl;
}

结果:

这是矩阵m:
  3  -1
2.5 1.5
这是向量v:
4
3

6.逗号初始化

示例代码:

int main()
{
    Matrix3f m;
    m << 1,2,3,
        4,5,6,
        7,8,9;
    std :: cout << m <<endl;
}

结果:

1 2 3
4 5 6
7 8 9

7.调整

可以通过rows(),cols()和size()检索矩阵的当前大小。这些方法分别返回行数,列数和系数数。调整动态大小矩阵的大小由resize()方法完成。

示例代码:

int main()
{

    MatrixXd m(2,5);
    m.resize(4,3);
    std :: cout << "矩阵m的大小" << m.rows() << "x" << m.cols()<< std :: endl;
    std :: cout << "它有" << m.size()<< "系数" << std :: endl;


    VectorXd v(2);
    v.resize(5);
    std :: cout << "向量v的大小为" << v.size()<< std :: endl;
    std :: cout << "作为矩阵,v的大小" << v.rows()<< "x" << v.cols()<< std :: endl;

}

结果:

矩阵m的大小4x3
它有12系数
向量v的大小为5
作为矩阵,v的大小5x1

8.分配和调整大小

这里实际上是个C++ 中等号的重载

Eigen自动调整左侧的矩阵大小,使其与右侧大小的矩阵大小相匹配。例如:

示例代码:

int main()
{

    MatrixXf a(2,2);
    std :: cout << "a is size " << a.rows() << "x" << a.cols()<< std :: endl;
    MatrixXf b(3,3);
    a = b;
    std :: cout << "a现在大小" << a.rows()<< "x" << a.cols()<< std :: endl;
}

结果:

a is size 2x2
a现在大小3x3

四、矩阵和向量算数

1.加减

二元运算符+如 a+b
二元运算符 - 如 a-b
一元算子 - 如同 -a
复合运算符+ =如 a+=b
复合运算符 - =如 a-=b

注意:

运算符的左值和右值,必须要有相同的类型和相同数量的行列

示例代码:

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 << "做一个+ = b;" << std :: endl;
    a += b;
    std :: cout << "现在 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;
}

2.标量的乘除

二元运算符如 matrixscalar
二元运算符如 scalarmatrix
二元运算符/如 matrix/scalar
复合运算符 =如 matrix=scalar
复合运算符/ =如 matrix/=scalar

示例代码:

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 << "做v *= 2;" << std :: endl;
    v *= 2;
    std :: cout << "现在v = \n" << v << std :: endl;
}

结果:

a * 2.5 =
2.5   5
7.5  10
0.1 * v =
0.1
0.2
0.3
做v *= 2;
现在v =
2
4
6

3.转置、共轭、伴随

通过成员函数transpose(),conjugate()和adjoint()分别获得矩阵或向量的转置$ a ^ T $,共轭$ \ bar {a} $和伴随(即,共轭转置)。$ a ^ * $$ a $

示例代码:

int main()
{

    MatrixXf a = MatrixXf :: Random(2,2);
    cout << "这是矩阵a \n" << a << endl;
    cout << "这是矩阵a 的转置\n" << a.transpose()<< endl;
    cout << "这是矩阵a 的共轭\n" << a.conjugate()<<endl;
    cout << "这是矩阵a 的伴随\n" << a.adjoint()<< endl;

}

结果:

这是矩阵a
-0.997497 -0.613392
 0.127171  0.617481
这是矩阵a 的转置
-0.997497  0.127171
-0.613392  0.617481
这是矩阵a 的共轭
-0.997497 -0.613392
 0.127171  0.617481
这是矩阵a 的伴随
-0.997497  0.127171
-0.613392  0.617481

4.矩阵 - 矩阵和矩阵 - 向量乘法

示例代码:

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

五、高级初始化

1.将矩阵进行拼接

请记住,必须先设置大小,然后才能使用逗号初始值设定项

示例代码:

int main()
{

    RowVectorXd vec1(3);
    vec1 << 1, 2, 3;
    std::cout << "vec1 = " << vec1 << std::endl;
    RowVectorXd vec2(4);
    vec2 << 1, 4, 9, 16;
    std::cout << "vec2 = " << vec2 << std::endl;
    RowVectorXd joined(7);
    joined << vec1, vec2;
    std::cout << "joined = " << joined << std::endl;

}

结果:

vec1 = 1 2 3
vec2 =  1  4  9 16
joined =  1  2  3  1  4  9 16

我们可以使用相同的技术来初始化具有块结构的矩阵。

实例代码:

int main()
{

    MatrixXf matA(2, 2);
    matA << 1, 2, 3, 4;
    MatrixXf matB(4, 4);
    matB << matA, matA/10, matA/10, matA;
    std::cout << matB << std::endl;

}

结果:

  1   2 0.1 0.2
  3   4 0.3 0.4
0.1 0.2   1   2
0.3 0.4   3   4

更高级的填充:

示例代码:

int main()
{

    Matrix3f m;
    m.row(0) << 1, 2, 3;
    m.block(1,0,2,2) << 4, 5, 7, 8;
    m.col(2).tail(2) << 6, 9;
    std::cout << m;

}

结果:

1 2 3
4 5 6
7 8 9

2.特殊矩阵

矩阵和数组都有特殊方法 Zero()

示例代码:

int main()
{
    std::cout << "A fixed-size array:\n";
    Array33f a1 = Array33f::Zero();
    std::cout << a1 << "\n\n";
    std::cout << "A one-dimensional dynamic-size array:\n";
    ArrayXf a2 = ArrayXf::Zero(3);
    std::cout << a2 << "\n\n";
    std::cout << "A two-dimensional dynamic-size array:\n";
    ArrayXXf a3 = ArrayXXf::Zero(3, 4);
    std::cout << a3 << "\n";

}

结果:

A fixed-size array:
0 0 0
0 0 0
0 0 0

A one-dimensional dynamic-size array:
0
0
0

A two-dimensional dynamic-size array:
0 0 0 0
0 0 0 0
0 0 0 0

类似地:

1.静态方法Constant(value)将所有系数设置为value。如果需要指定对象的大小,则附加参数将在value参数之前,如MatrixXd::Constant(rows, cols, value)。

2.方法Random()用随机系数填充矩阵或数组。

3.可以通过调用Identity()获得单位矩阵; 此方法仅适用于Matrix,而不适用于Array,因为“单位矩阵”是线性代数概念。

4.LinSpaced方法(大小,低,高)仅适用于向量和一维数组;

它产生一个指定大小的向量,其系数在low和之间等间隔high。

Eigen定义了实用函数

如setZero(),MatrixBase :: setIdentity()和DenseBase :: setLinSpaced(),可以方便地执行此操作。以下示例对比了构造矩阵的三种方法

使用静态方法和赋值,使用静态方法和逗号初始化程序,或使用setXxx()方法。

示例代码:

int main()
{

    const int size = 6;
    MatrixXd mat1(size, size);
    mat1.topLeftCorner(size/2, size/2)     = MatrixXd::Zero(size/2, size/2);
    mat1.topRightCorner(size/2, size/2)    = MatrixXd::Identity(size/2, size/2);
    mat1.bottomLeftCorner(size/2, size/2)  = MatrixXd::Identity(size/2, size/2);
    mat1.bottomRightCorner(size/2, size/2) = MatrixXd::Zero(size/2, size/2);
    std::cout << mat1 << std::endl << std::endl;


    MatrixXd mat2(size, size);
    mat2.topLeftCorner(size/2, size/2).setZero();
    mat2.topRightCorner(size/2, size/2).setIdentity();
    mat2.bottomLeftCorner(size/2, size/2).setIdentity();
    mat2.bottomRightCorner(size/2, size/2).setZero();
    std::cout << mat2 << std::endl << std::endl;


    MatrixXd mat3(size, size);
    mat3 << MatrixXd::Zero(size/2, size/2), MatrixXd::Identity(size/2, size/2),
            MatrixXd::Identity(size/2, size/2), MatrixXd::Zero(size/2, size/2);
    std::cout << mat3 << std::endl;

}

结果:

0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0

0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0

0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0

3.用作临时对象

静态方法如Zero()和Constant()可用于在声明时或在赋值运算符的右侧初始化变量。您可以将这些方法视为返回矩阵或数组; 实际上,它们返回所谓的表达式对象,在需要时可以计算矩阵或数组。

示例代码:

int main()
{

    MatrixXd m = MatrixXd::Random(3,3);
    m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
    cout << "m =" << endl << m << endl;
    VectorXd v(3);
    v << 1, 2, 3;
    cout << "m * v =" << endl << m * v << endl;
}

结果:

m =
10.1251 90.8741 45.0291
66.3585 68.5009 99.5962
29.3304 57.9873  92.284
m * v =
326.961
502.149
422.157

六、数组

1.概念:

Array是一个类模板,采用与Matrix相同的模板参数

Array <typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime>

我们采用的形式是ArrayNt形式的typedef代表一维数组,其中N和t是大小和标量类型。对于二维数组,我们使用ArrayNNt形式的typedef。

下表显示了一些示例:

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

2.访问Array中的值

括号运算符被重载以提供对数组系数的写和读访问,就像使用矩阵一样。此外,<<操作符可用于初始化数组(通过逗号初始化程序)或打印它们。

示例代码:

#include <iostream>
#include <Eigen/Dense>

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

3.加减

添加和减去两个数组与矩阵相同。如果两个阵列具有相同的大小,则该操作有效,并且以系数方式进行加法或减法。

数组还支持表单的表达式,该表达式为数组中的array + scalar每个系数添加标量。这提供了一种不能直接用于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

4.数组乘法

首先,当然你可以用一个标量乘以一个数组,这与矩阵的工作方式相同。数组与矩阵根本不同的是,当你将两个数组相乘时。矩阵将乘法解释为矩阵乘积,并且数组将乘法解释为系数乘积。因此,当且仅当它们具有相同的尺寸时,两个阵列可以相乘。

示例代码:

#include <iostream>
#include <Eigen/Dense>

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

5.其他系数运算

例如,.abs()方法取每个系数的绝对值,而.sqrt()计算系数的平方根。如果你有两个相同大小的数组,你可以调用.min(.)来构造数组,其系数是两个给定数组的相应系数的最小值。以下示例说明了这些操作。

示例代码:

#include <iostream>
#include <Eigen/Dense>

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.99499
0.254341
-1.22678
 1.23496
0.340037
a.abs() =
 1.99499
0.254341
 1.22678
 1.23496
0.340037
a.abs().sqrt() =
 1.41244
0.504323
  1.1076
 1.11129
0.583127
a.min(a.abs().sqrt()) =
-1.99499
0.254341
-1.22678
 1.11129
0.340037

七、在数组和矩阵表达式之间转换

什么时候应该使用Matrix类的对象?何时应该使用Array类的对象?您不能对数组应用Matrix运算,也不能对矩阵应用Array运算。因此,如果你需要进行矩阵乘法等线性代数运算,那么你应该使用矩阵; 如果你需要进行系数运算,那么你应该使用数组。但是,有时它并不那么简单,但您需要同时使用Matrix和Array操作。在这种情况下,您需要将矩阵转换为数组或反向转换。无论选择将对象声明为数组还是矩阵,都可以访问所有操作。

矩阵表达式有一个.array()方法,可以将它们“转换”为数组表达式,因此可以轻松应用系数方法。相反,数组表达式具有.matrix()方法。与所有Eigen表达式抽象一样,这没有任何运行时成本(假设您让编译器进行优化)。即.array()和.matrix()可被用作右值和作为左值。

Eigen禁止在表达式中混合矩阵和数组。例如,您无法直接添加矩阵和数组; 该规则的例外是赋值运算符:允许将矩阵表达式赋给数组变量,或者将数组表达式赋给矩阵变量。

以下示例说明如何通过使用.array()方法对Matrix对象使用数组操作

示例代码1:

#include <iostream>
#include <Eigen/Dense>

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()计算它们的矩阵乘积。

示例代码2:

#include <iostream>
#include <Eigen/Dense>

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

求矩阵的行列式

八、实例应用

1. 求矩阵的行列式

m.determinant()

注意:矩阵m要是double 类型,要不然报错

下面是我写的一个生成 32x32 位 01 可逆矩阵的类,这里面我在生成32位矩阵的时候使用的是矩阵的拼接技术,但是这样就会出现大量的数组,并且不能用循环实现,很尴尬。

示例代码:

#include <iostream>
#include <Eigen/Dense>
#include <cstdlib>
#include <ctime>
#include <cmath>

using namespace Eigen;
using namespace std;
typedef Matrix <double,32,32> Matrix32d;


class cM32{

public:

    Matrix32d create(){//返回一个可逆的32x32 随机 01 矩阵

        Matrix32d m = createPT32();
        if(check(m)) {
            cout << "可逆 " << "行列式为: " << m.determinant() << endl;
            return m;
        }else{
            cout << "不可逆" << endl;
            create();
        }
    }


private:

    Matrix32d createPT32(){//创建一个随机的32x32 的01矩阵
        Matrix32d m5;
        Matrix2d* arrayM =  new Matrix2d[256];
        for(int i=0;i<256;i++){
            arrayM[i] = create2();
        }

        m5 << arrayM[0], arrayM[1], arrayM[2], arrayM[3], arrayM[4], arrayM[5], arrayM[6], arrayM[7], arrayM[8], arrayM[9], arrayM[10], arrayM[11], arrayM[12], arrayM[13], arrayM[14], arrayM[15], arrayM[16],
                arrayM[17], arrayM[18], arrayM[19], arrayM[20], arrayM[21], arrayM[22], arrayM[23], arrayM[24], arrayM[25], arrayM[26], arrayM[27], arrayM[28], arrayM[29], arrayM[30], arrayM[31], arrayM[32],
                arrayM[33], arrayM[34], arrayM[35], arrayM[36], arrayM[37], arrayM[38], arrayM[39], arrayM[40], arrayM[41], arrayM[42], arrayM[43], arrayM[44], arrayM[45], arrayM[46], arrayM[47], arrayM[48],
                arrayM[49], arrayM[50], arrayM[51], arrayM[52], arrayM[53], arrayM[54], arrayM[55], arrayM[56], arrayM[57], arrayM[58], arrayM[59], arrayM[60], arrayM[61], arrayM[62], arrayM[63], arrayM[64],
                arrayM[65], arrayM[66], arrayM[67], arrayM[68], arrayM[69], arrayM[70], arrayM[71], arrayM[72], arrayM[73], arrayM[74], arrayM[75], arrayM[76], arrayM[77], arrayM[78], arrayM[79], arrayM[80],
                arrayM[81], arrayM[82], arrayM[83], arrayM[84], arrayM[85], arrayM[86], arrayM[87], arrayM[88], arrayM[89], arrayM[90], arrayM[91], arrayM[92], arrayM[93], arrayM[94], arrayM[95], arrayM[96],
                arrayM[97], arrayM[98], arrayM[99], arrayM[100], arrayM[101], arrayM[102], arrayM[103], arrayM[104], arrayM[105], arrayM[106], arrayM[107], arrayM[108], arrayM[109], arrayM[110], arrayM[111],
                arrayM[112], arrayM[113], arrayM[114], arrayM[115], arrayM[116], arrayM[117], arrayM[118], arrayM[119], arrayM[120], arrayM[121], arrayM[122], arrayM[123], arrayM[124], arrayM[125], arrayM[126],
                arrayM[127], arrayM[128], arrayM[129], arrayM[130], arrayM[131], arrayM[132], arrayM[133], arrayM[134], arrayM[135], arrayM[136], arrayM[137], arrayM[138], arrayM[139], arrayM[140], arrayM[141],
                arrayM[142], arrayM[143], arrayM[144], arrayM[145], arrayM[146], arrayM[147], arrayM[148], arrayM[149], arrayM[150], arrayM[151], arrayM[152], arrayM[153], arrayM[154], arrayM[155], arrayM[156],
                arrayM[157], arrayM[158], arrayM[159], arrayM[160], arrayM[161], arrayM[162], arrayM[163], arrayM[164], arrayM[165], arrayM[166], arrayM[167], arrayM[168], arrayM[169], arrayM[170], arrayM[171],
                arrayM[172], arrayM[173], arrayM[174], arrayM[175], arrayM[176], arrayM[177], arrayM[178], arrayM[179], arrayM[180], arrayM[181], arrayM[182], arrayM[183], arrayM[184], arrayM[185], arrayM[186],
                arrayM[187], arrayM[188], arrayM[189], arrayM[190], arrayM[191], arrayM[192], arrayM[193], arrayM[194], arrayM[195], arrayM[196], arrayM[197], arrayM[198], arrayM[199], arrayM[200], arrayM[201],
                arrayM[202], arrayM[203], arrayM[204], arrayM[205], arrayM[206], arrayM[207], arrayM[208], arrayM[209], arrayM[210], arrayM[211], arrayM[212], arrayM[213], arrayM[214], arrayM[215], arrayM[216],
                arrayM[217], arrayM[218], arrayM[219], arrayM[220], arrayM[221], arrayM[222], arrayM[223], arrayM[224], arrayM[225], arrayM[226], arrayM[227], arrayM[228], arrayM[229], arrayM[230], arrayM[231],
                arrayM[232], arrayM[233], arrayM[234], arrayM[235], arrayM[236], arrayM[237], arrayM[238], arrayM[239], arrayM[240], arrayM[241], arrayM[242], arrayM[243], arrayM[244], arrayM[245], arrayM[246],
                arrayM[247], arrayM[248], arrayM[249], arrayM[250], arrayM[251], arrayM[252], arrayM[253], arrayM[254], arrayM[255];
        return m5;
    }

    Matrix2d create2(){//创建 2x2 的01随机矩阵
        Matrix2d m1;
        m1(0,0) = rand()%2;
        m1(1,0) = rand()%2;
        m1(0,1) = rand()%2;
        m1(1,1) = rand()%2;
        return m1;
    }

    int check(Matrix32d m){//检查是不是可逆的

        if(fabs(m.determinant())){
            return 1;
        }else{
            return 0;
        }
    }

};

int main(){
    srand((unsigned int)time(NULL));
    cM32 *m = new cM32;
    for(int i=0;i<1000;i++){
        m->create();

    }
}
文章目录
  1. 1. 一、Eigen 是什么
  2. 2. 二、如何配置
  3. 3. 三、Eigen 基础
    1. 3.1. 1.Matrix 类
      1. 3.1.1. 1.基本:
      2. 3.1.2. 2.向量
      3. 3.1.3. 3.动态值
      4. 3.1.4. 4.构造函数
      5. 3.1.5. 5.系数访问器
      6. 3.1.6. 6.逗号初始化
      7. 3.1.7. 7.调整
      8. 3.1.8. 8.分配和调整大小
  4. 4. 四、矩阵和向量算数
    1. 4.1. 1.加减
    2. 4.2. 2.标量的乘除
    3. 4.3. 3.转置、共轭、伴随
    4. 4.4. 4.矩阵 - 矩阵和矩阵 - 向量乘法
  5. 5. 五、高级初始化
    1. 5.1. 1.将矩阵进行拼接
    2. 5.2. 2.特殊矩阵
    3. 5.3. 3.用作临时对象
  6. 6. 六、数组
    1. 6.1. 1.概念:
    2. 6.2. 2.访问Array中的值
    3. 6.3. 3.加减
    4. 6.4. 4.数组乘法
    5. 6.5. 5.其他系数运算
  7. 7. 七、在数组和矩阵表达式之间转换
  8. 8. 八、实例应用
    1. 8.1. 1. 求矩阵的行列式
|