特色技术

专业从事预应力结构体系的设计、施工一体化解决方案

资讯分类

线性代数计算库Eigen(三)

  • 分类:程序技术
  • 作者:
  • 来源:
  • 发布时间:2018-10-20 15:17
  • 访问量:

【概要描述】(五)初始化:  1、在C++中,定义与初始化是两个不同的概念和阶段,可以单独定义变量,也可以在定义变量的同时初始化变量。  2、C++要求对所有用到的变量作强制定义,也就是必须“先定义,后使用”。C语言要求变量的定义应该放在所有的执行语句之前,而C++则放松了限制,只要求在第一次使用该变量之前进行定义即可。也就是说,它可以出现在语句的中间。  3、C++要求对变量作强制定义的目的是:  1)凡未

线性代数计算库Eigen(三)

【概要描述】(五)初始化:  1、在C++中,定义与初始化是两个不同的概念和阶段,可以单独定义变量,也可以在定义变量的同时初始化变量。  2、C++要求对所有用到的变量作强制定义,也就是必须“先定义,后使用”。C语言要求变量的定义应该放在所有的执行语句之前,而C++则放松了限制,只要求在第一次使用该变量之前进行定义即可。也就是说,它可以出现在语句的中间。  3、C++要求对变量作强制定义的目的是:  1)凡未

  • 分类:程序技术
  • 作者:
  • 来源:
  • 发布时间:2018-10-20 15:17
  • 访问量:
详情

  (五)初始化:

  1、在C++中,定义与初始化是两个不同的概念和阶段,可以单独定义变量,也可以在定义变量的同时初始化变量。

  2、C++要求对所有用到的变量作强制定义,也就是必须“先定义,后使用”。 C语言要求变量的定义应该放在所有的执行语句之前,而C++则放松了限制,只要求在第一次使用该变量之前进行定义即可。也就是说,它可以出现在语句的中间。

  3、C++要求对变量作强制定义的目的是:

  1) 凡未被事先定义的,不作为变量名,这就能保证程序中变量名使用得正确。

  2) 每一个变量被指定为一确定类型,在编译时就能为其分配相应的存储单元。

  3) 指定每一变量属于一个特定的类型,这就便于在编译时,据此检查该变量所进行的运算是否合法。

  4、当定义没有初始化的变量时,系统有可能会为我们进行隐式的初始化,至于系统是否帮我们隐式初始化变量,以及为变量赋予一个怎么的初始值,这要取决于该变量的类型以及变量的定义域。

  5、局部变量必须初始化,否则其值未定义;

  (1)内置类型int,char,bool,float,double,指针、枚举enum等;

  (2)结构体、类、类模板等取决于它们自身的默认构造函数。类成员变量在对象创建的时候分配内存,如果在类中没有进行初始化,与局部内置类型结果一样;

  (3)STL库中vector、list、map等默认构造出一个空的容器。

  6、全局变量

  (1)内置类型默认初始化。int-->0,char-->“”,bool-->false(0);

  (2)类、结构体如果默认构造函数中没有初始化的成员变量,执行(1)方式初始化;

  7、C++初始化变量一共有四种方式

  (1)等于号,用”=”初始化

  例:int a = 0;

  在等号的右边输入初始值。

  (2)括号:

  例:int a(0);

  在括号的中间输入初始值。

  (3)花括号+等于号,’{}’+’=’初始化,又称为初始化列表

  例:int a={0};

  在等号右边的花括号里面输入值。

  (4)花括号,{} 声明,又称为初始化列表

  例:int a{0};

  在花括号里面输入值。

  8、Eigen逗号初始化器:

  (1)使用所谓的逗号初始化器语法可以方便地设置矩阵和向量的元素值。这个逗号初始化器实际上是Eigen重载了”<<“运算符。

  例如:

  Matrix3f m;

  m << 1, 2,3,

  4, 5, 6,

  7, 8, 9;

  std::cout<< m;

  这段代码输出为:

  1 2 3

  4 5 6

  7 8 9

  需要说明一下,逗号初始化器从左上角开始向左、向下移动。对象的大小需要事先指定,如果逗号初始化器列出的元素过多或者过少,Eigen将会给出警告。

  (2)此外,初始化列表的元素本身可以是向量或矩阵。一个常见的用途是将向量或矩阵连接在一起。例如,下面是如何将两个行向量连接在一起。请记住,必须先设置大小,然后才能使用逗号初始化器。

  例如:

  RowVectorXdvec1(3);

  vec1 << 1,2, 3;

  std::cout<< "vec1 = " << vec1 << std::endl;

  RowVectorXdvec2(4);

  vec2 << 1,4, 9, 16;

  std::cout<< "vec2 = " << vec2 << std::endl;

  RowVectorXdjoined(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

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

  例如:

  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

  (4)逗号初始化器也可用于填充块表达式,如m.row(I)。下面是获得与上面第一个示例相同的结果的更复杂的方法:

  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

  (5)矩阵和数组类都有像Zero()这样的静态方法,可用于将所有系数初始化为零。该方法有三个重载版本。

  A、第一个版本:变量不带参数,只能用于固定大小的对象。

  B、如果要将动态大小的对象初始化为零,则需要指定大小。因此,第二种重载函数需要一个参数,可以用于一维动态大小的对象,而第三种重载版本需要两个参数,可以用于二维对象。所有这三个变体都在下面的示例中进行了说明:

  std::cout<< "A fixed-size Matrix:\n";

  Matrix33f a1 = Matrix33f::Zero();

  std::cout<< a1 << "\n\n";

  std::cout<< "A one-dimensional dynamic-size Matrix:\n";

  MatrixXf a2 = MatrixXf::Zero(3);

  std::cout<< a2 << "\n\n";

  std::cout<< "A two-dimensional dynamic-size Matrix:\n";

  MatrixXXf a3 = MatrixXXf::Zero(3,4);

  std::cout<< a3 << "\n";

  输出:

  A fixed-size Matrix:

  0 0 0

  0 0 0

  0 0 0

  A one-dimensional dynamic-size Matrix:

  0

  0

  0

  A two-dimensionaldynamic-size Matrix:

  0 0 0 0

  0 0 0 0

  0 0 0 0

  (6) 同样,静态方法Constant(value)将所有元素设置为value。如果需要指定对象的大小,则附加的参数放在值参数之前,如MatrixXd::Constant(row,col,value)。

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

  单位矩阵的初始化可以用Identity()方法,只适用于Matrix类,而不适用于Array类,因为“单位矩阵”是一个线性代数概念。

  linspaced方法(size, low, high)只适用于Vectors和一维数组;它生成指定大小的Vectors,其系数在low和high之间等距。

  (7)下面的示例演示了LinSpaced()方法,它打印出一个表,表中的角度以度为单位,对应的角度以弧度为单位,以及它们的正弦和余弦。

  ArrayXXf table(10,4);

  table.col(0) =ArrayXf::LinSpaced(10, 0, 90);

  table.col(1) =M_PI / 180 * table.col(0);

  table.col(2) =table.col(1).sin();

  table.col(3) =table.col(1).cos();

  std::cout<< " Degrees Radians Sine Cosine\n";

  std::cout<< table << std::endl;

  输出:

  Degrees Radians Sine Cosine

  0 0 0 1

  10 0.175 0.174 0.985

  20 0.349 0.342 0.94

  30 0.524 0.5 0.866

  40 0.698 0.643 0.766

  50 0.873 0.766 0.643

  60 1.05 0.866 0.5

  70 1.22 0.94 0.342

  80 1.4 0.985 0.174

  90 1.57 1 0.0

  (8)最后的例子:

  这个例子显示可以将类似于由LinSpaced()返回的对象分配给变量(和表达式)。eigen定义了像setZero(),MatrixBase:setIdEntity()和DenseBase:setLinSpaced()这样的实用函数来方便地完成这一任务。它用三个方法来构造J矩阵,即静态方法、逗号初始化器和SetXxx()方法。

  const int size =6;

  MatrixXdmat1(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;

  MatrixXdmat2(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;

  MatrixXdmat3(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

  (未完待续)

扫二维码用手机看