类Matrix编写全记录(1)

第一部分:Matrix的编写缘由

1、深入研究矩阵的相关属性,以及与属性相关的语言实现方法

2、作为阅读<<C++ Template>>过程中练习。

3、作为提供给我将来使用的库的一部分。

 

第二部分:Matrix的概貌

1、由于matrix类主要是面向想我这样的程序设计者,所以采用模板来实现。

2、由于Matrix类打算被用作数学库的一部分,所以我尽可能编写得标准,功能完善。

3、Matrix类提供迭代器,以配合STL算法的使用。

4、Matrix类除了实现矩阵的简单存取功能以外,还实现相关的矩阵变换操作、行列式的计算(如果是  方 阵的话)。

5、Matrix类不能在线程之间共享。

6、Matrix类实现+ - ×  矩阵转置、矩阵分块、矩阵求秩等功能。

 

第三部分:编写中的问题(FAQ)

1、把十分简单却绝对不能错的常用表达式表示成用#define语句声明的宏。如,数组下标的offset可以用一个宏来封装,这样在编写过程中能够保证不会出现如此低级却致命的错误。一旦出现这种错误,有可能消耗你三四倍编写一个strcat函数的时间。

2、在模板的编写中会出现很多模板的参数表、class-id。class-id有一些是经常使用的,并且很多时候都具有一定的意义。这时候,可以使用typedef关键字在类声明前部首先定义。在定义的时候用一个简短并且有意义的组合标识符,一方面可以减少以后字符的输入量,另一方面可以减少由于编写过程中粗心大意造成的错误(漏符号)和提高程序可读性。虽然有很多人觉得这样好像没有太大必要,但是我们却没有看到过一个好的类库不使用这种方法以使程序变得简洁,可读性强。

例子:

 typedef Matrix<M,N,T>            ThisType;
 typedef const ThisType          Const_ThisType;
 typedef Matrix<N,M,T>            TranMatrix;
 typedef const TranMatrix        Const_TranMatrix;

另外,我们可以看到早在C语言时代,这个关键字就非常流行。可以说几乎每一份有质量的代码都会有它的踪迹。我们知道曾经有很多人抱怨过C语言可移植性不够强。这些呼声或多或少让typedef这个关键字更受欢迎了。实际上,当我们用typedef 这个关键字为某一种数据类型定义别名,并且使用该别名的时候就屏蔽了与特定机器有关的数据在底层的处理的差别。这样,如果我们想把我们的代码从32位机移植到64位机上,就只需要简单地修改一下用typedef声明的数据类型就行了,而不用在每一个使用该类型的地方进行修改。也就是说,typedef关键字从一定程度上提高了程序的可移植性。

我在第一次编写的时候就没有留意这个问题,所以当我后面修改的时候浪费了很多时间!

3、编写的时候要时刻记住现在编写的是什么类型的类。这很重要!因为类型不同会让你使用不同不同的方式对待同一个操作。有时候合理使用inline是一个好方法。

4、关键字const是一个能够使类结构严谨清晰的东西。如果一个成员函数不会修改本类的成员的话,const是一个明智的选择。

5、在模板类里面也许你很容易就能写出一个函数能够接受多种类型的参数(member template).。但是,我发现过度使用这用灵活性会使得这个类失去较严格的数据类型检查。由此导致的后果也许会使得代码意外地低效,因为有可能每一步赋值运算都会让系统调用类型转换函数(低效)。这也许只是低效的原因之一。所以,我觉得这种特性不应该用在矩阵的运算函数里面,但是如果在构造函数中使用却能扩大这个类的构造能力。该特性也可以用在设置数据成员的函数里面使用。

6、如果使用了member template定义一个成员函数,就没必要再编写一个和本类相容的成员函数。

除非,这两种问题的实作有所不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
实现有两个 CVector 存放数据的自定义动态数组,采用一维动态数组存储矩阵数据 CMatrix 实现的矩阵 使用的时候包含#include "Matrix.h"就行 CMatrix的接口函数都在"Matrix.h"里面 CVector的接口函数在"Vector.h"里,"Matrix.h"里包含了"Vector.h" 具体用法与测试用例Main.cpp里有3个测试用例,分别是针对构造函数属性计算与运算符重载的 内已包含测试工程xp\vc6.0\上亲测通过,并经过BoundsChecker测试没有内存泄漏。有兴趣的童鞋可以下作参考。 注意: 1、下标都是从0开始,数学课上矩阵下标都是从1开始,但是工作后习惯0开始,矩阵M的第一个元素是M(0,0) 2、型定死为double,原来作业是模板,由于vc6对模版支持不好,另矩阵计算double比较理想、整型几乎只能作加减 提供了多种初始化方式,int[]、float[]、double[]均可构造初始化,或则先构造出CVector再由CVector初始化。 3、定义了一个最大允许误差#define permit_eof (1.0e-13),判断相等使用宏 #define EQUAL(a,b) ( ((b) - (a) < permit_eof)&&((a) - (b) < permit_eof) ? (TRUE) : (FALSE) ) 正常输出的时候绝对值小于permit_eof 的时候清零处理,想要指定精度输出请用PrintOut 鸣谢:CSDN上supermegaboy君的C/C++左值性精髓,读后略有所感,空闲时重构了下大学时的作业,着重区分了函数返回值的左右值 =================================================附录:接口函数========================================================================== 开放的接口: CVector //构造函数 CVector(); virtual ~CVector(); CVector(const size_t &nSize;); CVector(const CVector & vIn);//拷贝构造函数 CVector(const double* const pData,const size_t &nSize;); CVector(const float* const pData,const size_t &nSize;); CVector(const int* const pData,const size_t &nSize;); //公开的成员函数 double at(const size_t& uIndex)const;//作右值 BOOL push_back(const double& dbIn ); BOOL resize(const size_t& nSize); size_t size()const; //重载操作符 double& operator()(const UINT& uIndex);//重载()运算符,可作左值 //重载的运算符 double& operator()(const size_t& xr,const size_t& xc);//重载()运算符,可作左值 CVector& operator=(const CVector &);//重载=运算符 double operator*(const CVector & )const;//重载*运算符,两向量相乘 CVector operator*(const double α)const;//重载*运算符,向量乘以实数alpha CVector& operator*=(const double α);//重载*=算符,向量乘以实数alpha CVector operator+(const CVector & )const;//重载+运算符,向量加上向量 CVector& operator+=(const CVector & );//重载+=算符,向量加上向量 CVector operator-(const CVector & )const;//重载+运算符,向量加上向量 CVector& operator-=(const CVector & );//重载+=算符,向量加上向量 CVector operator+(const double α)const;//重载+运算符,向量加上实数alpna CVector& operator+=(const double α);//重载+=算符,向量加上实数alpha BOOL operator==(const CVector &)const;//重载==运算符 BOOL operator!=(const CVector &)const;//重载!=运算符 CMatrix //构造函数 CMatrix(); virtual ~CMatrix(); CMatrix(const CMatrix&);//拷贝构造函数 CMatrix(const size_t& n);//产生n阶单位阵 CMatrix(const size_t& nrow, const size_t& ncol);// CMatrix(const size_t& nrow, const size_t& ncol,const CVector& xdata);//产生nrow行,ncol列矩阵数据由xdata初始化 CMatrix(const size_t& nrow, const size_t& ncol,const double*const pData); CMatrix(const size_t& nrow, const size_t& ncol,const float* const pData); CMatrix(const size_t& nrow, const size_t& ncol,const int* const pData); //公开的成员函数 double At(const size_t& xr,const size_t& xc) const;//这个只能作为右值 CMatrix Trans()const;//A.T()返回矩阵A的转置副本 CVector diag()const;//矩阵上三角化后的对角向量//以此求矩阵的秩,矩阵的行列式等 double det()const;//求矩阵行列式 size_t rank()const;//矩阵的秩 CMatrix Inv()const;//求逆矩阵 inline BOOL IsNullMatrix()const{ return (BOOL)(m_nRowlen==0 || m_nCollen == 0);};//是否是空矩阵 BOOL IsSingularMatrix()const;//是否是奇异矩阵//即行列式为0 友函数 //科学计数法输出//想看较精确的数据的时候 friend void void PrintOut(const CMatrix& M,const size_t& nprecision = 6,std::ostream& os = std::cout); //产生的随机方阵,一般会是非异阵,供测试用 friend CMatrix randMatrix(const size_t &uSize;,int MAX);//随机产生n阶的方阵 //--------------------------重载部分-Overloaded Part---------------------------------- CMatrix& operator=(const CMatrix &);//重载=赋值运算符 double& operator()(size_t xr,size_t xc);//重载()运算符,A(i,j)即矩阵A的i行j列的元素, friend std::ostream & operator<<(std::ostream & ,const CMatrix &);//重载<<,可用cout输出矩阵 friend std::ostream & operator<<(std::ostream & ,const CVector&);//重载<<,可用cout输出向量 friend std::istream & operator>>(std::istream & CMatrix &);//重载>>,可用cin输入矩阵 CMatrix operator*(const double α)const;//重载*运算符,矩阵乘以实数alpha CVector operator*(const CVector &)const;//重载*运算符,矩阵乘以向量 CMatrix operator*(const CMatrix &)const;//重载*运算符,矩阵相乘 CMatrix& operator*=(const CMatrix &);//重载*=运算符 CMatrix operator^(const int α)const;//重载^幂运算符,A^alpha,alpha可以为负整数 CMatrix operator+(const CMatrix &)const;//重载+运算符,矩阵相加 CMatrix& operator+=(const CMatrix &);//重载+=运算符 CMatrix operator-(const CMatrix &)const;//重载- CMatrix& operator-=(const CMatrix &);//重载-=运算符 BOOL operator==(const CMatrix &)const;//重载==运算符,判断矩阵是否相等 BOOL operator!=(const CMatrix &)const;//重载!=运算符,判断矩阵是否不相等 CVector operator/(const CVector &)const;//重载/除运算符,向量左除矩阵,求Ax=b的x向量
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值