计算数学精解【2】-C++计算基础(2)

正则表达式

基础

  • 正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。
  • 更多请见百度百科

regex_match

测试正则表达式是否与整个目标字符串相匹配。这是一种完全匹配,不是部分匹配

#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <regex>
using namespace std;

vector<string> split(const string &text, char separator) {
    vector<string> tokens;
    stringstream ss(text);
    string item;
    while (getline(ss, item, separator)) {
        if (!item.empty()) {
            tokens.push_back(item);
        }
    }
    return tokens;
}

string removeSpaces(const string& input) {
    string result = input;
    result.erase(std::remove(result.begin(), result.end(), ' '), result.end());
    return result;
}

int main(){
    string codeStr = "x:int=88.11;y:int=11;z:int=99";
    char delimiter = ';';
    vector<string> codeTokens=split(codeStr,delimiter);
    vector<string> symbolTokens,sysmbolVarTokens;
    regex strRx(R"((\d+)(\.)(\d+))");
    smatch match;
    for (const std::string &codeLineToken : codeTokens) {
        delimiter = '=';
        symbolTokens=split(codeLineToken,delimiter);
        delimiter = ':';
        sysmbolVarTokens=split(symbolTokens[0],delimiter);
        if (removeSpaces(sysmbolVarTokens[1])=="int"){
            string intSysbol=removeSpaces(sysmbolVarTokens[0]);
            string value=removeSpaces(symbolTokens[1]);
            bool found = regex_match(value, match, strRx);
            if (found)
                 cout <<"非法赋值" <<intSysbol<<":"<<value<< endl;
            else{
                 cout << "合法赋值" <<intSysbol<<":"<<value<< endl;
            }



        }
   }


    return (0);
}

非法赋值x:88.11
合法赋值y:11
合法赋值z:99

Process returned 0 (0x0)   execution time : 0.214 s
Press any key to continue.

regex_replace

替换匹配正则表达式。
所有大写字母全部用“.”替换。

#include <iostream>
#include <string>
#include <regex>
using namespace std;


int main(){
    string str = "aBjDEIFoo998089";
    regex strRx(R"([A-Z])");
    string fmt(".");
    smatch match;
    std::cout << "replacement == "
        << std::regex_replace(str, strRx, fmt) << std::endl;
    return (0);
   }


replacement == a.j....oo998089

Process returned 0 (0x0)   execution time : 0.220 s
Press any key to continue.

swap

交换两个 basic_regex 或 match_results 对象。

#include <iostream>
#include <string>
#include <regex>
using namespace std;


int main(){
    string str = "a99jDEIFoo998089";
    regex strRx1(R"([A-Z]+)");
    regex strRx2;
    smatch match1;
    smatch match2;
    swap(strRx1, strRx2);
    bool found =regex_search(str, match2, strRx2);
    if (found)
        cout<<match2.str()<<endl;
    return (0);
   }


#include <iostream>
#include <string>
#include <regex>
using namespace std;


int main(){
    string str = "a99jDEIFoo998089";
    regex strRx1(R"([A-Z]+)");
    regex strRx2;
    smatch match1;
    smatch match2;
    swap(strRx1, strRx2);
    bool found =regex_search(str, match2, strRx2);
    swap(match1, match2);
    if (found)
        cout<<match1.str()<<endl;
    return (0);
   }


DEIF

Process returned 0 (0x0)   execution time : 0.197 s
Press any key to continue.

Eigen

概述

  • Eigen是一个用于线性代数的c++模板库:矩阵、向量、数值求解器和相关算法。
  • 除了c++标准库之外,Eigen没有任何依赖关系。
  • 具体见Eigen

简单例子

#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::MatrixXd;
using Eigen::VectorXd;

int main()
{
  MatrixXd m = MatrixXd::Random(3,3);
  m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
  std::cout << "m =" << std::endl << m << std::endl;
  VectorXd v(3);
  v << 1, 2, 3;
  std::cout << "m * v =" << std::endl << m * v << std::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

Process returned 0 (0x0)   execution time : 0.168 s
Press any key to continue.

Matrix

基础

  • 所有矩阵和向量都是Matrix模板类的对象。
  • 向量也是矩阵,单行或单列。
  • Matrix模板类6个参数,常用就3个参数,其它3个参数有默认值。
Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

分别是元素标量类型,编译时行数和列数
-下面定义float类型元素,4*5的矩阵

typedef Matrix<float, 4, 4> Matrix4f;
  • 4*1列 向量
typedef Matrix<float, 4, 1> Vector3f;
  • 1*2行向量
typedef Matrix<int, 1, 2> RowVector2i;
  • 运行时再指定维度
typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
typedef Matrix<int, Dynamic, 1> VectorXi;
//只指定行
Matrix<float, 3, Dynamic>
MatrixXf a(10,15);
VectorXf b(30);
  • 初始化元素
Vector2i a(1, 2);                      
Matrix<int, 5, 1> b {1, 2, 3, 4, 5};   
Matrix<int, 1, 5> c = {1, 2, 3, 4, 5}; 

编译时固定尺寸
  • Matrix4f
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::Matrix4f;

int main()
{
  Matrix4f m = Matrix4f::Random();
  std::cout << m << std::endl;
}


 -0.997497   0.170019    0.64568   0.421003
  0.127171 -0.0402539    0.49321  0.0270699
 -0.613392  -0.299417  -0.651784   -0.39201
  0.617481   0.791925   0.717887  -0.970031

Process returned 0 (0x0)   execution time : 0.099 s
Press any key to continue.


  • Vector3f
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::Vector3f;

int main()
{
  Vector3f m = Vector3f::Random();
  std::cout << m << std::endl;
}


-0.997497
 0.127171
-0.613392

Process returned 0 (0x0)   execution time : 0.103 s
Press any key to continue.
  • RowVector2i
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::RowVector2i;

int main()
{
  RowVector2i m = RowVector2i::Random();
  std::cout << m << std::endl;
}


-16343   2083

Process returned 0 (0x0)   execution time : 0.091 s
Press any key to continue.

  • 指定大小
    6*6的矩阵
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::Matrix;
typedef Matrix<int,6,6> Matrix6i;
int main()
{
  Matrix6i m = Matrix6i::Random();
  std::cout << m << std::endl;
}


-16343  -4906   6897 -11557 -16092 -10937
  2083  12974    443 -10948  -4002   5342
-10050  10578  -6423  16007   1037  -1613
 10116   8080 -15893  -1780   2332  -4846
  2785 -10679 -13389 -12482   3334 -14515
  -660  11761  -4442 -16231   3511   3528

Process returned 0 (0x0)   execution time : 0.101 s
Press any key to continue.
运行指定大小
  • double型元素
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::MatrixXf;
int main()
{
  MatrixXf m = MatrixXf::Random(3,3);
  std::cout << m << std::endl;
}
 -0.997497   0.617481  -0.299417
  0.127171   0.170019   0.791925
 -0.613392 -0.0402539    0.64568

Process returned 0 (0x0)   execution time : 0.099 s
Press any key to continue.

  • int型元素
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::MatrixXi;
int main()
{
  MatrixXi m = MatrixXi::Random(3,3);
  std::cout << m << std::endl;
}


-16343  10116  -4906
  2083   2785  12974
-10050   -660  10578

Process returned 0 (0x0)   execution time : 0.098 s
Press any key to continue.

  • 指定元素值
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::Vector2i;
using Eigen::Matrix;
int main()
{
    Vector2i a(1, 2);
    Matrix<int, 5, 1> b {1, 2, 3, 4, 5};
    Matrix<int, 1, 5> c = {1, 2, 3, 4, 5};
    std::cout << a<< std::endl;
    std::cout << b<< std::endl;
    std::cout << c<< std::endl;
}
1
2
1
2
3
4
5
1 2 3 4 5

Process returned 0 (0x0)   execution time : 0.094 s
Press any key to continue.

矩阵元素定义

  • 定义每个元素值
    [ 1 3 2 4 ] \begin{bmatrix} 1& 3 \\2& 4 \end{bmatrix} [1234]
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"


using Eigen::MatrixXd;

int main()
{
  MatrixXd m(2,2);
  m(0,0) = 1;
  m(1,0) = 2;
  m(0,1) = 3;
  m(1,1) = 4;
  std::cout << m << std::endl;
}

1 3
2 4

Process returned 0 (0x0)   execution time : 0.151 s
Press any key to continue.

  • 随机矩阵
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"


using Eigen::MatrixXd;

int main()
{
  MatrixXd m = MatrixXd::Random(2,2);
  std::cout << m << std::endl;
}

-0.997497 -0.613392
 0.127171  0.617481

Process returned 0 (0x0)   execution time : 0.110 s
Press any key to continue.

矩阵加法

MatrixXd::Constant(4,4,10)是一个4*4的矩阵(方阵),每个元素都是10.

#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"


using Eigen::MatrixXd;

int main()
{
  MatrixXd m = MatrixXd::Random(4,4);
  std::cout << m << std::endl;
  m = (m + MatrixXd::Constant(4,4,10));
  std::cout << m << std::endl;
}
 -0.997497   0.170019    0.64568   0.421003
  0.127171 -0.0402539    0.49321  0.0270699
 -0.613392  -0.299417  -0.651784   -0.39201
  0.617481   0.791925   0.717887  -0.970031
 9.0025   10.17 10.6457  10.421
10.1272 9.95975 10.4932 10.0271
9.38661 9.70058 9.34822 9.60799
10.6175 10.7919 10.7179 9.02997

Process returned 0 (0x0)   execution time : 0.042 s
Press any key to continue.


#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"


using Eigen::MatrixXd;

int main()
{
  MatrixXd m = MatrixXd::Random(4,2);
  std::cout << m << std::endl;
  m = m + MatrixXd::Constant(4,2,10);
  std::cout << m << std::endl;
}

 -0.997497   0.170019
  0.127171 -0.0402539
 -0.613392  -0.299417
  0.617481   0.791925
 9.0025   10.17
10.1272 9.95975
9.38661 9.70058
10.6175 10.7919

Process returned 0 (0x0)   execution time : 0.114 s
Press any key to continue.

矩阵乘法

MatrixXd::Constant(2,4,10)是一个2*4的矩阵(方阵),每个元素都是10.

#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"


using Eigen::MatrixXd;

int main()
{
  MatrixXd m = MatrixXd::Random(4,2);
  std::cout << m << std::endl;
  m = m * MatrixXd::Constant(2,4,10);
  std::cout << m << std::endl;
}


 -0.997497   0.170019
  0.127171 -0.0402539
 -0.613392  -0.299417
  0.617481   0.791925
-8.27479 -8.27479 -8.27479 -8.27479
0.869167 0.869167 0.869167 0.869167
-9.12809 -9.12809 -9.12809 -9.12809
 14.0941  14.0941  14.0941  14.0941

Process returned 0 (0x0)   execution time : 0.291 s
Press any key to continue.

向量

  • VectorXd
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::MatrixXd;
using Eigen::VectorXd;
using namespace std;
int main()
{
  MatrixXd m = MatrixXd::Random(3,3);
  VectorXd v(3);
  v << 10, 20, 30;
  cout << "v =" << endl <<  v << endl;
  cout << "m * v =" << endl << m * v << endl;
}

v =
10
20
30
m * v =
-6.60787
 28.4298
 12.4314

Process returned 0 (0x0)   execution time : 0.167 s
Press any key to continue.

  • MatrixXd
    可使用矩阵函数定义向量
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"

using Eigen::MatrixXd;
using Eigen::VectorXd;
using namespace std;
int main()
{
  MatrixXd m = MatrixXd::Random(3,3);
  MatrixXd v(3,1);
  v(0,0) = 10;
  v(1,0) = 20;
  v(2,0) = 30;
  cout << "v =" << endl <<  v << endl;
  cout << "m * v =" << endl << m * v << endl;
}

编译时设置大小

本节前面的例子都是在运行时动态设置矩阵size,下面的例子是在编译时设置

#include <iostream>
#include <Eigen/Dense>
 
using Eigen::Matrix3d;
using Eigen::Vector3d;
 
int main()
{
  Matrix3d m = Matrix3d::Random();
  m = (m + Matrix3d::Constant(1.2)) * 50;
  std::cout << "m =" << std::endl << m << std::endl;
  Vector3d v(1,2,3);
  
  std::cout << "m * v =" << std::endl << m * v << std::endl;
}

矩阵初始化

多维矩阵

  • 数组
MatrixXi a {      // construct a 2x2 matrix
      {1, 2},     // first row
      {3, 4}      // second row
};
Matrix<double, 2, 3> b {
      {2, 3, 4},
      {5, 6, 7},
};
#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"


using Eigen::Matrix;
int main()
{
    Matrix<int,3,2> a {{1, 2}, {3, 4}, {5, 6}};
    std::cout << a<< std::endl;
}


1 2
3 4
5 6

Process returned 0 (0x0)   execution time : 0.117 s
Press any key to continue.



  • 重定向操作符
Matrix3f m;
m << 1, 2, 3,
     4, 5, 6,
     7, 8, 9;
std::cout << m;

1 2 3
4 5 6
7 8 9

矩阵和向量size

  • rows:矩阵行
  • cols:矩阵列
  • resize:重新规划size
#include <iostream>
#include "e:/eigen/Eigen/Dense"
using namespace std;
using namespace Eigen;
int main()
{
  MatrixXf m(2,5);
  cout << "The matrix m is of size "
            << m.rows() << "x" << m.cols() << std::endl;
  m.resize(4,3);
  cout << "The matrix m resized is of size "
            << m.rows() << "x" << m.cols() << std::endl;
  cout << "It has " << m.size() << " coefficients" << std::endl;
  VectorXf v(2);
  cout << "The vector v is of size " << v.size() << std::endl;
  v.resize(5);
  cout << "The vector v resized is of size " << v.size() << std::endl;
  cout << "As a matrix, v is of size "
            << v.rows() << "x" << v.cols() << std::endl;
}

The matrix m is of size 2x5
The matrix m resized is of size 4x3
It has 12 coefficients
The vector v is of size 2
The vector v resized is of size 5
As a matrix, v is of size 5x1

Process returned 0 (0x0)   execution time : 0.317 s
Press any key to continue.

固定大小or 动态大小

什么时候应该使用固定大小(例如Matrix4f),什么时候应该使用动态大小(例如MatrixXf)?

  • 简单的答案是:对于非常小的尺寸尽可能使用固定大小,对于较大的尺寸或必须使用动态大小。对于较小的大小,特别是小于(大约)16的大小,使用固定大小对性能非常有益,因为它允许Eigen避免动态内存分配并展开循环。
  • 当然,使用固定大小的限制是,只有在编译时知道大小时才有可能。此外,对于足够大的大小,例如大于(大约)32的大小,使用固定大小的性能优势变得可以忽略不计。
  • 更糟糕的是,尝试在函数内部使用固定大小创建一个非常大的矩阵可能会导致堆栈溢出,因为Eigen会尝试将数组自动分配为局部变量,而这通常是在堆栈上完成的。

Matrix类六个模板参数

  • 模板参数
Matrix<typename Scalar,
       int RowsAtCompileTime,
       int ColsAtCompileTime,
       int Options = 0,
       int MaxRowsAtCompileTime = RowsAtCompileTime,
       int MaxColsAtCompileTime = ColsAtCompileTime>

  • Options是位字段。
    RowMajor。它指定这种类型的矩阵使用行为主存储顺序;默认情况下,存储顺序是以列为主的。请参阅存储订单页面。例如,此类型表示行为主的3x3矩阵:
  Matrix<float, 3, 3, RowMajor>
  • MaxRowsAtCompileTime和MaxColsAtCompileTime
    在需要指定时非常有用,即使在编译时不知道矩阵的确切大小,但在编译时知道一个固定的上限。这样做的最大原因可能是为了避免动态内存分配。例如,下面的矩阵类型使用12个浮点数的普通数组,没有动态内存分配
Matrix<float, Dynamic, Dynamic, 0, 3, 4>
  • 存储顺序详解
    矩阵和二维数组有两种不同的存储顺序:列为主和行为主
    当矩阵存储在内存中时,条目必须以某种方式线性排列。有两种主要的方法可以做到这一点,按行和按列。
  1. 如果一个矩阵是逐行存储的,我们就说它是按行主序存储 row-major的。首先存储整个第一行,然后是整个第二行,依此类推。以矩阵为例
    在这里插入图片描述
8 2 2 9 9 1 4 4 3 5 4 5 
  1. 如果一个矩阵是按列存储 column-major 的,那么它是以列为主顺序存储的,从整个第一列开始,然后是整个第二列,依此类推。若将上述矩阵按列主序存储,则其布局如下:
8 9 3 2 1 5 2 4 4 9 4 5 

3、例
定义一个4*3的矩阵A,然后分别以按行或按列存储。
使用PlainObjectBase::data()函数,该函数返回指向矩阵第一个条目的内存位置的指针。

#include <iostream>
#include "e:/eigen/Eigen/Dense"
using namespace std;
using namespace Eigen;
int main()
{
    Matrix<int, 4, 3, ColMajor> Acolmajor;
    Acolmajor << 1,2,3,4,
                 5,6,7,8,
                 9,10,11,12;
    cout << "The matrix A:" << endl;
    cout << Acolmajor << endl << endl;

    cout << "In memory (column-major):" << endl;
    for (int i = 0; i < Acolmajor.size(); i++)
      cout << *(Acolmajor.data() + i) << "  ";
    cout << endl << endl;

    Matrix<int, 4, 3, RowMajor> Arowmajor = Acolmajor;
    cout << "In memory (row-major):" << endl;
    for (int i = 0; i < Arowmajor.size(); i++)
      cout << *(Arowmajor.data() + i) << "  ";
    cout << endl;
}

The matrix A:
 1  2  3
 4  5  6
 7  8  9
10 11 12

In memory (column-major):
1  4  7  10  2  5  8  11  3  6  9  12

In memory (row-major):
1  2  3  4  5  6  7  8  9  10  11  12

Process returned 0 (0x0)   execution time : 0.404 s
Press any key to continue.
  • Matrix类模板有六个模板参数,其中三个是强制性的(Scalar, RowsAtCompileTime和ColsAtCompileTime),另外三个是可选的(Options, MaxRowsAtCompileTime和MaxColsAtCompileTime)。如果Options参数设置为RowMajor,则矩阵或数组按行主要顺序存储;如果设置为ColMajor,则按列主顺序存储。该机制在上述特征程序中用于指定存储顺序。

  • 如果未指定存储顺序,则Eigen默认以列为主的方式存储条目。如果使用方便类型(Matrix3f、ArrayXXd等)之一,也会出现这种情况。

  • 使用一种存储顺序的矩阵和数组可以分配给使用另一种存储顺序的矩阵和数组,就像上面的程序中使用Acolmajor初始化Arowmajor时发生的那样。Eigen将自动重新排序条目。更一般地说,行为主矩阵和列为主矩阵可以在表达式中混合使用。

  • 您应该在程序中使用哪种存储顺序呢?这个问题没有简单的答案;这取决于您的应用程序。以下是一些需要牢记的要点:

1.您的用户可能希望您使用特定的存储顺序。或者,您可以使用Eigen以外的其他库,这些库可能需要特定的存储顺序。在这些情况下,在整个程序中使用这种存储顺序可能是最简单和最快的。
2.当矩阵以行为主的顺序存储时,由于更好的数据局部性,逐行遍历矩阵的算法将运行得更快。类似地,对于列主矩阵,逐列遍历更快。为了找出适合您的特定应用程序的更快的方法,进行一些实验可能是值得的。
3.缺省情况下,Eigen是列为主的。自然地,大多数特征库的开发和测试都是用列主矩阵完成的。这意味着,尽管我们的目标是透明地支持列为主和行为主的存储顺序,但Eigen库可能最适合列为主的矩阵。

初始化向量

#include <iostream>
#include "f:/learn/eigen-3.4.0/Eigen/Dense"


using Eigen::VectorXd;
using Eigen::RowVectorXd;
int main()
{
    VectorXd a {{1.5, 2.5, 3.5}};
    RowVectorXd b {{1.0, 2.0, 3.0, 4.0}};
    std::cout << a<< std::endl;
    std::cout << b<< std::endl;
}


1.5
2.5
3.5
1 2 3 4

Process returned 0 (0x0)   execution time : 0.110 s
Press any key to continue.





元素类型

MatrixNt for Matrix<type, N, N>. For example, MatrixXi for Matrix<int, Dynamic, Dynamic>.
MatrixXNt for Matrix<type, Dynamic, N>. For example, MatrixX3i for Matrix<int, Dynamic, 3>.
MatrixNXt for Matrix<type, N, Dynamic>. For example, Matrix4Xd for Matrix<d, 4, Dynamic>.
VectorNt for Matrix<type, N, 1>. For example, Vector2f for Matrix<float, 2, 1>.
RowVectorNt for Matrix<type, 1, N>. For example, RowVector3d for Matrix<double, 1, 3>.
  • N可以是2、3、4或X中的任意一个(表示动态)。
  • T可以是I (int)、f (float)、d (double)、cf (complex)或CD (complex)中的任意一个。虽然只为这五种类型定义了类型定义,但这并不意味着它们是唯一受支持的标量类型

参考文献

  1. Eigen
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值