n阶矩阵求逆矩阵C++面向对象.docx
- 文档编号:12368644
- 上传时间:2023-04-18
- 格式:DOCX
- 页数:19
- 大小:331.39KB
n阶矩阵求逆矩阵C++面向对象.docx
《n阶矩阵求逆矩阵C++面向对象.docx》由会员分享,可在线阅读,更多相关《n阶矩阵求逆矩阵C++面向对象.docx(19页珍藏版)》请在冰豆网上搜索。
n阶矩阵求逆矩阵C++面向对象
课程设计报告
信息系统开发语言
(一)课程设计
——n阶方阵求逆的实现
一、课程设计目的
1、了解什么是矩阵及逆矩阵。
2、通过VC++6.0编写一个实现求矩阵逆矩阵的程序。
3、巩固和加深学生对算法课程基本知识的理解和掌握。
4、培养利用算法知识解决实际问题的能力。
5、掌握利用程序设计语言进行算法程序的开发、调试、测试.
6、掌握书写算法设计说明文档的能力。
7、提高综合运用算法、程序设计语言、数据结构知识的能力。
二、问题描述
给出任意一个维数大于1小于256的矩阵,通过程序求出其逆矩阵。
如
,存在矩阵B,使得矩阵A与B的乘积为单位矩阵,则称矩阵B为矩阵A的逆矩阵。
三、问题分析
根据矩阵与逆矩阵的定义,即矩阵A与矩阵B相乘等于单位矩阵的思路,编辑程序。
为使问题更加简单明了化,现举除一个具体例子,便于理解,我们在求解数学题目中,经常会遇到这一类的题目:
如求方阵A的逆矩阵
拿到这个题,我们首先应该是理解什么叫矩阵及逆矩阵,我们根据定义可知,一个矩阵如果存在逆矩阵,那么这个矩阵的秩一定不会小于该矩阵的维数,拿到一个题,要求一个逆矩阵的方法是很多的,比较常用的还是先把矩阵化为上三角或者下三角矩阵,,判断矩阵是否存在逆矩阵,然后,然后根据矩阵与逆矩阵之积等于单位矩阵从而得出逆矩阵,这是比较一般的思路,我们一下设计基本上也是以此为基础的。
四、算法分析、设计与描述
1.算法分析和设计
对于矩阵求逆,逆矩阵的定义是:
对于n阶方阵A,若存在矩阵B,使得AB=BA=E,则称A为可逆矩阵,简称A可逆,并称B为A的逆矩阵。
A存在逆矩阵的充要条件是|A|≠0。
若用定义的方法求解,计算量大,当矩阵的阶数很大时很浪费时间,为了节省时间,通过查阅资料和上网搜索,决定采用高斯-约旦发来进行方阵的求逆操作。
对于矩阵的乘法,利用矩阵乘法定义即可实现,矩阵的乘法的定义是:
若A是一个m*n阶矩阵,B是一个n*p阶矩阵,则AB=C是一个m*p阶矩阵,而C中的每一个(i,j)元都等于A的第i行中的各元和B的第j列的各对应元之乘积的和。
只要按照该定义就可以求出两个矩阵的乘积。
2.算法描述
a.高斯-约旦法求解逆矩阵的算法描述如下:
首先,对于k从0到n-1作如下几步:
1)从第k行、第k列开始的右下角子阵中选取绝对值最大的元素,并记住次元素所在的行号和列号,在通过行交换和列交换将它交换到主元素位置上。
这一步称为全选主元。
2)m(k,k)=1/m(k,k)
3)m(k,j)=m(k,j)*m(k,k),j=0,1,...,n-1;j!
=k
4)m(i,j)=m(i,j)-m(i,k)*m(k,j),i,j=0,1,...,n-1;i,j!
=k
5)m(i,k)=-m(i,k)*m(k,k),i=0,1,...,n-1;i!
=k
最后,根据在全选主元过程中所记录的行、列交换的信息进行恢复,恢复的原则如下:
在全选主元过程中,先交换的行(列)后进行恢复;原来的行(列)交换用列(行)交换来恢复。
2.算法描述(可插入流程图)
五、程序设计
1.程序设计的基本思路
该程序设计了一个类,用于存储用户数据的方阵阶数、用户输入的方阵数据以及方阵的逆矩阵数据。
因为用户需要计算的方阵的阶数不定,因此采用了double型指针动态开辟内存的方式来存储用户输入的方阵数据和逆矩阵数据。
同时,该类定义了等方法,用来实现最成员变量的初始化,方阵求逆,矩阵相乘的操作。
程序运行开始,首先调用类的方法,在该方法中首先要求用户输入矩阵的阶数,并根据该阶数开辟内存空间,接着要求用户输入方阵的数据,输入完毕后,程序调用类的方法用以实现方阵的求逆,在求逆过程中,首先判断该矩阵是否存在逆矩阵,若存在则进行求逆,若不存在则给出提示并要求用户重新输入。
求逆完成后存储结果并显示,同时程序调用类的方法对两个矩阵进行相乘操作,用来验证求逆结果是否正确。
该程序设计的主要难点和重点在于方阵的逆矩阵求解方法,通过复习矩阵的相关知识和查阅资料,决定采用高斯-约旦法来实现对方阵的求逆,为了计算的方便,数据也是采用一维数据而不是二维数据才存储。
矩阵类matrix的uml图如下:
2.程序代码及说明
#include
#include
usingnamespacestd;
double**B;//保存矩阵A与E的组合矩阵
intN=0;
voidInit()
//初始化B但是还没有输入A的值
{
cout<<"现在请该矩阵输入的维数N"< do{ cin>>N; if(N<1)cout<<"检查矩阵的维数是否正确! "< }while(N<1); B=newdouble*[N+1];//B[0][n]不用 inti; for(i=0;i<=N;++i) B[i]=newdouble[2*N+1];//B[n][0]不用 intj; for(i=0;i<=N;++i) for(j=0;j<=2*N;++j) B[i][j]=(j-i==N)? 1: 0; } voidAinit() //输入原矩阵每一行的每一个数的值 { cout<<"请输入原矩阵每一行的每一个数的值: "< inti,j; for(i=1;i<=N;++i) { cout<<"输入第"< "< for(j=1;j<=N;++j) cin>>B[i][j]; } cout<<"该矩阵为: "< for(i=1;i<=N;++i) { for(j=1;j<=N;++j) cout< cout< } } intTo1(inti) //在进行矩阵变成上三角是将第i行第i列的数变成1 //并且返回是否变换成功 //0---失败,也就是说改矩阵的秩不是N,并不能求出逆矩阵 //1---成功,返回后进行下一步程序 { intj; intii=i; doubleij; if(B[ii][ii]! =0)ij=B[ii][ii]; else { for(j=i+1;j<=N;++j) if(B[j][i]! =0) break; if(j>N)return0;//失败 for(;i<=2*N;++i)//将第j行的加到第ii行 B[ii][i]+=B[j][i]; ij=B[ii][ii]; } for(i=ii;i<=2*N;++i)//将第ii行第ii列的变为1 B[ii][i]/=ij; return1;//成功返回 } voidTo0(inti,intj) //利用第i行第i列的数将第j行到第i行的第i列变为0 { if(i==j)return; intii=i,jj=j; doubleij; intn=(i -1: 1; //在下面是j+=n //n用来检验是求上三角,还是下三角 //-1-------i //1------i>j也就是将上三角变为0 for(;j! =i;j+=n) for(ii=i,ij=B[j][i];ii<=2*N;++ii) B[j][ii]-=ij*B[i][ii]; } voidPrint() { inti,j; intn=N*2; cout< for(i=1;i<=N;i++) { for(j=N+1;j<=n;++j) cout< cout< } } //intTo1(inti) //在进行矩阵变成上三角是将第i行第i列的数变成1 //voidTo0(inti,intj) //利用第i行第i列的数将第j行到第i行的第i列变为0 voidmain() { Init();//初始化B但是还没有输入A的值 Ainit();//输入原矩阵每一行的每一个数的值 inti; intflag=1; for(i=1;i { if(To1(i)) To0(i,N); else { cout<<"改矩阵的秩小于N,没有逆矩阵"< } } for(i=N;i>=1&&flag==1;--i) { if(To1(i)) To0(i,0); else { cout<<"改矩阵的秩小于N,没有逆矩阵"< } } if(flag==1)Print(); cin>>i; } 六、程序运行、调试和结果分析 1.程序运行中出现的问题及调试手段(包括异常处理) 在运行过程中是出现过很多问题的,错误也是非常之多的,就是各种不能运行,先就针对错误比较突出的一些问题进行分析,错误一的提示: fatalerrorC1083: Cannotopenincludefile: 'stdafx.h': Nosuchfileordirectory 执行cl.exe时出错.根据英文提示,才发现原来在设置代码时我按照以前编辑程序的经验预定义了一个头文件“stdafx.h”,当我把头文件“stdafx.h”省去再次运行时,该错误就已经解决。 错误二的提示: warningC4508: 'main': functionshouldreturnavalue;'void'returntypeassumed 对于这个问题,是不应该犯的错误,这个错误的错误源在于编辑代码的最后一个阶段,并没有注意到int定义的函数是有返回值的而void定义的函数才没有返回值,于是我将int改成了void,此处错误就解决了。 具体错误代码如下: intmain() { //定义一个矩阵类 matrixm; //调用该类的set_data方法,来对其内部成员变量赋值 m.set_data(); //对输入的矩阵求逆,如果求逆失败,说明输入的矩阵不存在逆矩阵,则要求用户重//新输入 while(m.InverseMatrix()==1) m.set_data(); //求逆成功后,计算两个矩阵的乘积是否为单位矩阵,用以验证求解的正确性 m.Cheng(); } 错误三的提示: errorC2143: syntaxerror: missing';'before'}' 类似于错误三的错误是非常多的,这在编辑程序时是最容易出错,也是最容易被遗忘的。 在编辑程序时,我们必须要有严谨认真的态度,防止类似于错误二和错误三的情况发生。 还有一个很奇怪的现象就是连接是显示的是0个错误,但是检测却出现了一个错误,但是却可以运行,比如图一所示: 图一 图二 这个问题经过仔细研究后,发现在在图二中如果选择的是: “是”的话,则运行不了,如果选择“否”就可以正常运行,并出现以上情况,出现以上情况的原因是这个文件夹是我很早以前建立的,做这个实验的时候我并没有重新建立文件夹,而是利用了以前做实验时,建好的文件,直接修改了文件里面的程序,直接进行调试、检测以及运行,只要重新建立文件,就可以解决以上问题了,重新建立文件夹后,运行情况如图三 图三 2.程序运行结果分析(多组数据测试) 运行中的第一种情况如图四: 图四 当输入的维数为0时,显示的文字为: 逆矩阵为空,两矩阵相乘结果也为空, 这是如下程序的运行结果 matrix: : matrix() { //将矩阵阶数初始化为0,并将两个指针指向NULL。 row=0; in_buffer=NULL; out_buffer=NULL; } matrix: : ~matrix() { //如果指针依然指向内存,则将指针指向的内存释放掉,并将指针指向NULL if(in_buffer) { delete[]in_buffer; in_buffer=NULL; } if(out_buffer) { delete[]out_buffer; out_buffer=NULL; } } 运行中的第二种情况: 此矩阵没有逆矩阵,是因为该矩阵的秩不等于该矩阵的维数2,设该矩阵用A表示,也就是该矩阵的lAl=0,这是如下代码中的结果,在矩阵中,矩阵的秩小于改矩阵的维数,该矩阵是没有逆矩阵的,这有矩阵逆矩阵的定义就知道了。 代码如下: for(k=0;k { doublemax=0; //全选主元 //寻找最大元素 for(i=k;i { for(j=k;j { //寻找最大值 if(fabs(*(out_buffer+i*row+j))>max) { max=*(out_buffer+i*row+j); is[k]=i; js[k]=j; } } } //如果最大值为0,则不存在逆矩阵,要求用户重新输入 if(0==max) { cout<<"该矩阵不存在逆矩阵,请重新输入"< return1; } 运行中的第三种情况: 由程序设定以及逆矩阵的性质可知,以上输入的矩阵是符合要求的,故输入后可以得到逆矩阵,经过多次试验可知,只要维数大于1小于256,且符合矩阵逆矩阵的定义,根据以上程序都是可以执行的。 七、总结与体会 我只能说C++这门课真的是太高深莫测了,你还能再复杂一点吗? 可是更让我觉得意外的是以前一直以为学C++知识为了开发软件应用软件什么的,没想到连我最喜欢的数学都可以这样来解决啊! 我上课其实基本是还是蛮认真的,但是拿到题目却是愕然的呀! 原以为是很简单的东西没想到细究起来其实这么复杂,所有我深深的明白没有浅显的知识,只有浅显的理解啊。 知识还是要一步一个脚印的扎稳啊,不能半知半解,要不然其实很不懂没什么区别! 经过这次试验我深深明白,上课听老师讲讲是远远不够的,一天24个小时,我们有8个小时在睡觉,8个小时在上课,那么决定我们生命长度以及宽度的就是那课余的8小时,所以,课后的时间我们应该好好利用,用心的学习,达到不懂到懂,懂到精的境界! 不要小看任何事,任何简单的背后都会有不简单。 在学习C++以前,我认为C++只是在C语言的基础上的一种延伸,认为只要学过C语言,就可以用C语言的那种设计思想来学习C++、设计C++程序。 正是由于抱了这种错误的思想,使我在一开始学习C++的时候遇到了很大的困难,我没有办法体会面向对象的设计思想,我在学习这门课的时候老是想着实现这个函数功能的具体过程,而没太注意对象分类的重要性。 随着课程学习的深入,我感觉到了利用类和对象、继承、封装等一系列知识可以把我们程序中很多繁杂、重复的部分省略掉,还可以解决一些利用面向过程的设计思想无法解决的问题,我自己也试着编写一些小的C++程序,当然在这个过程中遇到了很多困难,其中调试带来的困难让我无法忘记,在调试程序的同时,我也总结出来了一些调试的小技巧,让我在C语言课程设计中也受用匪浅。 在学习这门课的过程中,我感受到了自己亲自动手编程序、调程序的重要性,我们要熟悉C++的语法、体会调试的思想,最好的一个手段就是自己动手编程、调试,这会比我们一味的看书效果好得多。 另外,我还感觉到要编一个程序出来。 严谨认真的态度是非常重要的,没有一个严谨认真的态度,是做不成什么事情的,很多时候,我们出现的问题不是我们不懂,而是我们的粗心大意导致了我们的错误连篇,出现错误的时候我们就必须检查和纠正,这也是非常费时费力的,所以无论是在工作中还是在学习中,我们都必须抱着认真严谨的态度来面对任何事,只有这样才可以事半功倍。 同时我也认识到同学之间的相互帮助以及同学之间的相互促进使非常重要的,在为这个论文设计奋战了几天几夜之后,在查找程序几处提示错误的时候,自己怎么都找不到错误在哪里,于是就向同学寻求帮助,他们一下子就找到了我的错误,我想这就是当局者迷旁观者清吧,我们被自己的思想禁锢了,在生活也是如此,多听别人的意见、多与别人交流,会更有益于我们的成长。 很高兴能够了解到C++的神奇魅力和面向对象程序设计的独特思想,它为我今后的程序设计奠定了基础。 感谢老师对我们的悉心教授! 课程设计成绩评定表 等级 成绩 组成 优秀 良好 中等 及格 不及格 报 告 文 档 1.文档很规范。 2.排版很清晰。 3.内容很全面。 4.设计很合理。 1.文档规范。 2.排版清晰。 3.内容全面。 4.设计合理。 1.文档较规范。 2.排版较清晰。 3.内容较全面。 4.设计较合理。 1.文档欠规范。 2.排版欠清晰。 3.内容欠全面。 4.设计欠合理。 1.文档不规范。 2.排版不清晰。 3.内容不全面。 4.设计不合理。 算 法 分 析 1.算法正确。 2.算法分析很全面。 3.算法描述很清晰。 1.算法正确。 2.算法分析全面。 3.算法描述清晰。 1.算法正确。 2.算法分析较全面。 3.算法描述较清晰。 1.算法基本正确。 2.算法分析欠全面。 3.算法描述欠清晰。 1.算法不正确。 2.算法分析不全面。 3.算法描述不清晰。 程 序 实 现 1.程序设计思路很清晰。 2.程序代码编写很完整。 3.程序运行正确。 1.程序设计思路清晰。 2.程序代码编写完整。 3.程序运行正确。 1.程序设计思路较清晰。 2.程序代码编写较完整。 3.程序运行正确。 1.程序设计思路欠清晰。 2.程序代码编写欠完整。 3.程序运行基本正确。 1.程序设计思路不清晰。 2.程序代码编写不完整。 3.程序运行不正确。 结 果 分 析 1.有运行结果描述。 2.结果描述很清晰、很完整。 3.结果分析很深入。 1.有运行结果描述。 2.结果描述清晰、完整。 3.结果分析深入。 1.有运行结果描述。 2.结果描述较清晰、较完整。 3.结果分析较深入。 1.有运行结果描述。 2.结果描述欠清晰、欠完整。 3.结果分析欠深入。 1.无运行结果描述。 2.结果描述不清晰、很完整。 3.结果分析不深入。 实 习 总 结 1.有实验总结。 2.实验总结很全面、很深入。 3.能从实验中总结出创新成果。 1.有实验总结。 2.实验总结全面、深入。 3.能从实验中总结出创新成果。 1.有实验总结。 2.实验总结较全面、较深入。 1.有实验总结。 2.实验总结欠全面、欠深入。 1.无实验总结。 2.实验总结不全面、不深入。 综合成绩评定: 评阅老师(签章): 年月日
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 矩阵 C+ 面向 对象