<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
一、概述
1.设计原因
由于数值计算课的上机作业要求,为了减少创建成本,所以设计了一个基于标准 C++ 的 MATRIX 类。
2.设计目的
利用动态分配内存,运算符重载等机制,利用已经学会的内容,尽可能简化矩阵的创建、运算等过程。
3.主要功能
- 定义矩阵的方式:
-
MATRIX A;//创建空矩阵
MATRIX A(n);//创建一维矩阵,初始值为 n;
MATRIX A(MATRIX & B);//完全复制 B 矩阵创建 A
MATRIX A(MatrixType,Dimension,value1,(value2));//创建特殊矩阵(单位矩阵,对角矩阵,顺序矩阵,上三角矩阵,下三角矩阵)
MATRIX A(MatrixType,Dimension,band);//利用 band 字符串创建带状矩阵
- 计算矩阵属性,包括:
-
- 行列式的值
- 矩阵的特征值
- 矩阵的迹
- 矩阵的逆
- 矩阵的转置
- 矩阵运算,包括:
-
- 加法
- 减法
- 乘法
- 针对实数,将实数分配到矩阵的每一个元素上,所以可以进行 矩阵/实数 的运算
4.储存方式
由于目前处理的矩阵一般不超过 500 阶(约占用 1.9 MB 内存空间),所以暂时使用连续内存保存内容。
二、类设计图
项目 | 名称 | 备注 |
私有成员 | double *Body;//the content of the matrix |
|
int row;//the row of the matrix |
||
int col;//the column of the matrix |
||
char type;//matrix type:I,D,P,B,U,L,E,Z,N,R |
||
构造函数 | MATRIX();//default constructor |
|
MATRIX(int m,int n);//constructor |
||
MATRIX(const MATRIX & A);//copy constructor |
||
MATRIX(char t,int n,double val,int pRow=0);//I,D,U,L,P |
||
MATRIX(char t,int n,string & band);//B |
||
MATRIX(char t,int n,const char * band);//B |
||
MATRIX(double k);//k is a real number |
||
MATRIX(int k);//k is a real number |
||
MATRIX(int m,int n,const double * array)//use const array construct |
||
析构函数 | ~MATRIX();//destructor |
|
运算符重载 | MATRIX & operator +=(const MATRIX & A); |
|
MATRIX & operator -=(const MATRIX & A); |
||
MATRIX & operator *=(const MATRIX & A); |
||
MATRIX & operator = (const MATRIX & A); |
||
MATRIX & operator = (const double k); |
||
MATRIX & operator = (const int k); |
||
double & operator () (int i,int j) const; |
||
double & operator () (int i) const; |
||
功能函数 | double det();//determinant |
|
double trace();//trace |
||
double lambda(); |
||
MATRIX & inv();//inverse |
||
MATRIX & trans();//transposition |
||
支持函数 | void PrintMatrix(int width); |
|
void Input();//input the elements' value |
||
void setBody(int i,int j,double val);//set Body[i*row+j] |
||
int Row()const{return row;} |
||
int Column()const{return col;} |
||
char MatrixType()const{return type;} |
||
void setAll(double val);//set all elements a same value |
||
void PrintBody();//print all the elements |
项目 | 名称 | 备注 |
函数 | MATRIX operator +(const MATRIX & A,const MATRIX & B); |
|
MATRIX operator -(const MATRIX & A,const MATRIX & B); |
||
MATRIX operator *(const MATRIX & A,const MATRIX & B); |
||
MATRIX operator /(const MATRIX & A,const MATRIX & B); |
||
ostream & operator <<(ostream & out,MATRIX & A); |
四、成员函数说明
MATRIX()
默认构造函数,用于创建空的矩阵。矩阵类型和出错时一样为 E。MATRIX(int m,int n)
重载构造函数,生成 m×n 维矩阵,并初始化为零矩阵。出错生成 E 矩阵。MATRIX(const MATRIX & A)
复制构造函数,利用 A 矩阵重新构造一个新矩阵。出错生成 E 矩阵。MATRIX(char t,int n,double val,int pRow=0)
t 为类型,n 为阶数,val 为初始化使用的值(创建单位矩阵时不起作用,顺序矩阵时为第一个要替换的行),pRow 只在创建顺序矩阵时表示第二个需要替换的行。
创建特殊矩阵,包括:
单位矩阵 I
对角矩阵 D
顺序矩阵 P
上三角矩阵 U
下三角矩阵 LMATRIX(char t,int n,string & band)
t 为矩阵类型 B,n 为阶数,band 为用 string 类型创建的带,当用户需要动态输入带的内容时,使用此函数。MATRIX(char t,int n,const char * band)
t 为矩阵类型 B,n 为阶数,band 为用 const char * 类型创建的带,当编程时已经确定需要的带,即使用字符串常量,使用此函数。MATRIX(double k)
将 double 类型的 k 转换为一阶实矩阵,方便参与通用的矩阵运算。MATRIX(int k)
将 int 类型的 k 转换为一阶实矩阵,方便参与通用的矩阵运算。∼MATRIX()
析构函数,当 Body 不为空时,释放占用的内存。double det()
尚未设计,计算矩阵的行列式值。double trace()
计算矩阵的迹。double lambda()
尚未设计,计算矩阵的特征值。MATRIX & inv()
尚未设计,计算矩阵的逆。MATRIX & trans()
将调用它的矩阵转置。MATRIX & operator +=(const MATRIX & A)
MATRIX & operator -=(const MATRIX & A)
MATRIX & operator *=(const MATRIX & A)
重载各符合赋值运算符。MATRIX & operator = (const MATRIX & A)
MATRIX & operator = (const double k)
MATRIX & operator = (const int k)
重载赋值运算符,分别用于将一个矩阵赋值,一个 double 类型,一个 int 类型赋值给矩阵的情况。void PrintMatrix(int width)
打印整个矩阵,两个数之间打印一个空格,width 可以设置打印宽度,用于不整齐的矩阵输出。void Input()
完整从标准输入设备(键盘)输入一个矩阵的值,需要先创建再使用。void setBody(int i,int j,double val)
这是一个 MATRIX 类内部调用的函数,用于在一些重载情况重新为元素复制的情况,在一定情况下也可以用于修改矩阵某个特定元素的值。int Row() const
返回私有成员 row。int Column() const
返回私有成员 col。char MatrixType() const
返回私有成员 type。void setAll(double val)
一次性为矩阵所有元素赋予相同的值 val。void PrintBody()
以不换行的方式顺序输出 Body 的元素,每个数字紧跟一个 # 号为索引值。
五、应用举例
例程代码
#include "MATRIX.h"
using namespace std;
int main(int argc,char* argv[])
{
MATRIX M;
MATRIX N(3,5);
MATRIX I('I',4,20);//20 is invalid for I matrix
MATRIX U('U',10,3.5);
MATRIX L('L',10,7.5);
MATRIX P('P',10,3,6);
MATRIX B('B',8,"1,2,5,2,1");
cout<<"M:"<<endl
<<M<<endl
<<"N:"<<endl
<<N<<endl
<<"I:"<<endl
<<I<<endl
<<"U:"<<endl
<<U<<endl
<<"L:"<<endl
<<L<<endl
<<"P:"<<endl
<<P<<endl
<<"B:"<<endl
<<B<<endl;
cout<<"L:(in PrintMatrix(3))"<<endl;
L.PrintMatrix(3);
cout<<endl<<"U:(in PrintMAtrix(3))"<<endl;
U.PrintMatrix(3);
cout<<endl<<"M=L:"<<endl;
M=L;
M.PrintMatrix(4);
cout<<endl<<"M=22.5:"<<endl;
M=22.5;
cout<<M<<endl;
cout<<endl<<"M=P*U:"<<endl;
M=P*U;
M.PrintMatrix(3);
cout<<endl<<"M=U*L:"<<endl;
M=U*L;
M.PrintMatrix(6,2,true);
cout<<"M(1,2)=20:"<<endl;
M(1,2)=20;
M.PrintMatrix(6,2,true);
cout<<"NagB:"<<endl;
MATRIX NagB('B',5,"-1,5,-1");
NagB.PrintMatrix(2);
cout<<endl;
double array[]={1,2,3,4,5,6,7,8,0,-1,2.5,0,0,0,0,0,0,0,0,0};
MATRIX vector(1,20,array);
cout<<"vector={1,2,3,4,5,6,7,8,0,-1,2.5,0,0,0,0,0,0,0,0,0}"<<endl
<<"vector(5):"<<endl
<<vector(5)<<endl<<endl;
MATRIX vector2(20,1,array);
MATRIX V=vector*vector2;
cout<<V;
return 0;
}
运行结果
M:
N:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
I:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
U:
1 3.5 3.5 3.5 3.5 3.5 3.5 3.5 3.5 3.5
0 1 3.5 3.5 3.5 3.5 3.5 3.5 3.5 3.5
0 0 1 3.5 3.5 3.5 3.5 3.5 3.5 3.5
0 0 0 1 3.5 3.5 3.5 3.5 3.5 3.5
0 0 0 0 1 3.5 3.5 3.5 3.5 3.5
0 0 0 0 0 1 3.5 3.5 3.5 3.5
0 0 0 0 0 0 1 3.5 3.5 3.5
0 0 0 0 0 0 0 1 3.5 3.5
0 0 0 0 0 0 0 0 1 3.5
0 0 0 0 0 0 0 0 0 1
L:
1 0 0 0 0 0 0 0 0 0
7.5 1 0 0 0 0 0 0 0 0
7.5 7.5 1 0 0 0 0 0 0 0
7.5 7.5 7.5 1 0 0 0 0 0 0
7.5 7.5 7.5 7.5 1 0 0 0 0 0
7.5 7.5 7.5 7.5 7.5 1 0 0 0 0
7.5 7.5 7.5 7.5 7.5 7.5 1 0 0 0
7.5 7.5 7.5 7.5 7.5 7.5 7.5 1 0 0
7.5 7.5 7.5 7.5 7.5 7.5 7.5 7.5 1 0
7.5 7.5 7.5 7.5 7.5 7.5 7.5 7.5 7.5 1
P:
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 1
B:
5 2 1 0 0 0 0 0
2 5 2 1 0 0 0 0
1 2 5 2 1 0 0 0
0 1 2 5 2 1 0 0
0 0 1 2 5 2 1 0
0 0 0 1 2 5 2 1
0 0 0 0 1 2 5 2
0 0 0 0 0 1 2 5
L:(in PrintMatrix(3))
1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7.50 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7.50 7.50 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7.50 7.50 7.50 1.00 0.00 0.00 0.00 0.00 0.00 0.00
7.50 7.50 7.50 7.50 1.00 0.00 0.00 0.00 0.00 0.00
7.50 7.50 7.50 7.50 7.50 1.00 0.00 0.00 0.00 0.00
7.50 7.50 7.50 7.50 7.50 7.50 1.00 0.00 0.00 0.00
7.50 7.50 7.50 7.50 7.50 7.50 7.50 1.00 0.00 0.00
7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 1.00 0.00
7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 1.00
U:(in PrintMAtrix(3))
1.00 3.50 3.50 3.50 3.50 3.50 3.50 3.50 3.50 3.50
0.00 1.00 3.50 3.50 3.50 3.50 3.50 3.50 3.50 3.50
0.00 0.00 1.00 3.50 3.50 3.50 3.50 3.50 3.50 3.50
0.00 0.00 0.00 1.00 3.50 3.50 3.50 3.50 3.50 3.50
0.00 0.00 0.00 0.00 1.00 3.50 3.50 3.50 3.50 3.50
0.00 0.00 0.00 0.00 0.00 1.00 3.50 3.50 3.50 3.50
0.00 0.00 0.00 0.00 0.00 0.00 1.00 3.50 3.50 3.50
0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00 3.50 3.50
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00 3.50
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00
M=L:
1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7.50 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7.50 7.50 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7.50 7.50 7.50 1.00 0.00 0.00 0.00 0.00 0.00 0.00
7.50 7.50 7.50 7.50 1.00 0.00 0.00 0.00 0.00 0.00
7.50 7.50 7.50 7.50 7.50 1.00 0.00 0.00 0.00 0.00
7.50 7.50 7.50 7.50 7.50 7.50 1.00 0.00 0.00 0.00
7.50 7.50 7.50 7.50 7.50 7.50 7.50 1.00 0.00 0.00
7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 1.00 0.00
7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 1.00
M=22.5:
22.50
M=P*U:
1.00 3.50 3.50 3.50 3.50 3.50 3.50 3.50 3.50 3.50
0.00 1.00 3.50 3.50 3.50 3.50 3.50 3.50 3.50 3.50
0.00 0.00 0.00 0.00 0.00 1.00 3.50 3.50 3.50 3.50
0.00 0.00 0.00 1.00 3.50 3.50 3.50 3.50 3.50 3.50
0.00 0.00 0.00 0.00 1.00 3.50 3.50 3.50 3.50 3.50
0.00 0.00 1.00 3.50 3.50 3.50 3.50 3.50 3.50 3.50
0.00 0.00 0.00 0.00 0.00 0.00 1.00 3.50 3.50 3.50
0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00 3.50 3.50
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00 3.50
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00
M=U*L:
237.25 213.50 187.25 161.00 134.75 108.50 82.25 56.00 29.75 3.50
217.50 211.00 187.25 161.00 134.75 108.50 82.25 56.00 29.75 3.50
191.25 191.25 184.75 161.00 134.75 108.50 82.25 56.00 29.75 3.50
165.00 165.00 165.00 158.50 134.75 108.50 82.25 56.00 29.75 3.50
138.75 138.75 138.75 138.75 132.25 108.50 82.25 56.00 29.75 3.50
112.50 112.50 112.50 112.50 112.50 106.00 82.25 56.00 29.75 3.50
86.25 86.25 86.25 86.25 86.25 86.25 79.75 56.00 29.75 3.50
60.00 60.00 60.00 60.00 60.00 60.00 60.00 53.50 29.75 3.50
33.75 33.75 33.75 33.75 33.75 33.75 33.75 33.75 27.25 3.50
7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 1.00
M(1,2)=20:
237.25 20.00 187.25 161.00 134.75 108.50 82.25 56.00 29.75 3.50
217.50 211.00 187.25 161.00 134.75 108.50 82.25 56.00 29.75 3.50
191.25 191.25 184.75 161.00 134.75 108.50 82.25 56.00 29.75 3.50
165.00 165.00 165.00 158.50 134.75 108.50 82.25 56.00 29.75 3.50
138.75 138.75 138.75 138.75 132.25 108.50 82.25 56.00 29.75 3.50
112.50 112.50 112.50 112.50 112.50 106.00 82.25 56.00 29.75 3.50
86.25 86.25 86.25 86.25 86.25 86.25 79.75 56.00 29.75 3.50
60.00 60.00 60.00 60.00 60.00 60.00 60.00 53.50 29.75 3.50
33.75 33.75 33.75 33.75 33.75 33.75 33.75 33.75 27.25 3.50
7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 7.50 1.00
NagB:
5.00 -1.00 0.00 0.00 0.00
-1.00 5.00 -1.00 0.00 0.00
0.00 -1.00 5.00 -1.00 0.00
0.00 0.00 -1.00 5.00 -1.00
0.00 0.00 0.00 -1.00 5.00
vector={1,2,3,4,5,6,7,8,0,-1,2.5,0,0,0,0,0,0,0,0,0}
vector(5):
5.00
211.25
Process returned 0 (0x0) execution time : 0.641 s
Press any key to continue.
六、更新日志
- 2011.10.21
- 修正了带状矩阵不能处理负数的情况
- 增加了通过先定义 double 数组来初始化矩阵的构造函数,引入对应的 BUG
- 将重载运算符 () 返回值修改为 Body 的引用,这样可以使用 A(i,j)=A(m,l)+C;的式子
- 发现乘法中存在一个很大的 BUG,已经修正
- 2011.10.20
- MATRIX 已在上午能够正常工作
- 为了增强交互能力,又增加使用字符串常量构造带状矩阵的构造函数
- 重载流输出运算符 >>
- 开始使用 html 书写类使用说明书
- 2011.10.19
- 经过一夜的思考开始设计,MATRIX 类架构初步提出
- 设计完类的主要函数,类外主要成员函数
- 晚上已经能够完成加减乘除基本运算
- 2011.10.18
- 数值计算课得知更推荐使用 C++ 完成上机作业
- 开始设计 MATRIX 类,初步打算应当在编程的时候具有和 MATLAB 类似的方便程度
七、类的扩展
由于 MATRIX 类的设计初衷只是为了减轻同学们(包括我自己)在完成作业时的困难程度,所以类本身只是一个基础架构,能够良好的创建和管理需要的矩阵。真正的计算,诸如 Gauss 消去法,Jacobi 迭代,Gauss-Seidel 迭代等并没有设计在最初的 MATRIX 矩阵类当中,但是考虑将在会增加这些功能为内部函数。
另外,限于所学知识,MATRIX 并没有设计计算矩阵行列式值,特征值,逆等功能,但是已经为将来的功能留下了接口。
初版 MATRIX 类只使用动态数组连续内存保存数据,可以预见,这种保存方式对高阶矩阵的计算局限性很大,学习数据结构后将考虑新的数据保存方式。由于算法和数据结构联系紧密,采用新的数据结构很可能需要重写整个算法,所以在扩展数据结构时应当十分小心。
八、BUGs Report
可能存在的 BUG
带状矩阵中没有对空字符串,重复负号,重复逗号等做检查,可以考虑写一个将字符串标准化的函数。