您好,欢迎访问三七文档
目录一、课程设计的目的………………………………………………………1二、问题描述………………………………………………………………1三、问题分析………………………………………………………………1四、算法分析、设计与描述………………………………………………21.算法分析和设计………………………………………………………22.算法描述………………………………………………………………3五、程序设计………………………………………………………………61.程序设计的基本思路…………………………………………………62.程序代码及说明………………………………………………………8六、程序运行、调试和结果分析…………………………………………131.程序运行中出现的问题及调试手段(包括异常处理)……………132.程序运行结果分析(多组数据测试)………………………………16七、总结与体会……………………………………………………………19附录:课程设计成绩评定表信息系统开发语言课程设计一、课程设计目的1)实践C++语言程序设计和实现的全过程(分析、设计、调试等);2)掌握C++语言程序设计过程中综合知识的运用;3)检验、巩固所学的专业知识;4)培养同学们的综合素质和独立分析解决问题的能力。该课程设计的主要内容是C++语言程序设计的实现。与传统笔试考察课程学习情况相比,课程设计可以避免考试方式的片面性和局限性,有效地将同学们课堂上掌握的理论知识与其处理数据的业务能力相结合,提高同学们的知识运用和实际操作能力,尤其是培养同学们理论与实际相结合分析解决问题的能力。同时,也方便于检验同学们掌握该课程知识的广度、深度及对知识综合运用的能力。二、问题描述题目:n阶方阵求逆的实现总体需求:编写一个实现求矩阵逆矩阵的程序。功能需求:1)输入一个n(n256)阶方阵A,2)求出A的逆矩阵B,并输出。3)将A和B相乘得矩阵C,验证C是否为单位矩阵。用户界面的结果显示:输入:程序正常运行后,提示用户输入一个方阵A。输出:1)A的逆矩阵B。2)A与B相乘的结果矩阵C。三、问题分析a11a12…a1n形如a21a22…a2n的方阵,称为n阶方阵。…………an1an2…ann10…0n阶方阵01…0称为n阶单位矩阵,一般用字母E或I表示。…………00…1逆矩阵的定义:对于n阶方阵A,如果存在一个n阶方阵B,使AB=BA=E,则称A是可逆矩阵,B是A的逆矩阵。如果A是可逆的,则A的逆矩阵是唯一的,记为A-1。判断矩阵可逆的定理:n阶方阵A可逆的充分必要条件是|A|≠0,且当A可逆时,有A-1=(1/|A|)A*。矩阵乘法的定义:给定矩阵A=(aij)m×L及B=(bij)L×n,记cij=ai1b1j+ai2b2j+…+aiLbLj(i=1,2,…,m;j=1,2,…,n)。称矩阵(cij)m×n为矩阵A与B的积,L记作AB,即AB=(cij)m×n=(∑aikbkj)m×nk=1根据现有的线性代数知识,针对“n阶方阵求逆”的问题作如下的分析:求一个n阶方阵的逆矩阵,首先,要判断该方阵A是否可逆,即|A|≠0,方阵A可逆;否则,不可逆;其次,要知道一个n阶方阵的逆矩阵仍旧是一个n阶方阵。再者,通过初等变换法、分块矩阵法等方法求得一个方阵的逆矩阵后,还需要判断求得的逆矩阵是否正确,即AA-1=E,则逆矩阵A-1正确;否则,错误。最后,才能得到该方阵正确的逆矩阵。采用定义法求解,不管阶数是大是小,往往计算量大,当矩阵的阶数较大时,就会很浪费时间和精力。而且,编写程序,利用计算机求解n阶方阵的逆,最重要的是算法的选择,合适的算法可以简化计算,节省时间。所以,寻求合适的计算方法,显得尤为重要。四、算法分析、设计与描述1.算法分析和设计对于一个矩阵A,存在逆矩阵的充要条件是|A|≠0;如果存在一个n阶方阵B,使AB=BA=E,则称A是可逆矩阵,B是A的逆矩阵。而解决矩阵求逆问题的关键是求逆运算方法的选择。利用定义法的计算,工程浩大且费时,为了得到一种合适且节省时间的算法,我们查阅了大量的资料,进行了网上搜索,决定用高斯-约旦法来进行n阶方阵的求逆操作。为了数值计算的稳定性,整个求逆过程需要全选主元。高斯-约旦法求解逆矩阵:首先,要进行全选主元;再进行归一化计算;接着进行消元计算;然后,需要对经过全选主元后记录的行、列交换的信息进行恢复。矩阵求逆的计算工作量(乘除法次数)为O(n3)。最后,验证所求逆矩阵是否正确,需要利用矩阵乘法。对于矩阵的乘法,若A是一个m*n阶矩阵,B是一个n*p阶矩阵,则AB=C是一个m*p阶矩阵,而C中的每一个(i,j)元都等于A的第i行中的各元和B的第j列的各对应元之乘积的和。按照该定义便可求出原矩阵与其逆矩阵的乘积,从而得到结果是否为单位矩阵以验证求得的逆矩阵的正确性。2.算法描述(1)高斯-约旦法求解逆矩阵的算法描述如下:对于k=0,1,2,…,n-1作如下运算:1)全选主元:在A(k,k)右下方(包括A(k,k)在内)的n-k阶子阵中选取绝对值最大的元素,并将该元素所在的行号记录在is[k]中,而列号记录在js[k]中,然后,通过行交换与列交换将该绝对值最大的元素交换到主对角线A(k,k)的位置上,即以下两步:○1A(k,l)A(is[k],l),l=0,1,2,……,n-1○2A(l,k)A(l,js[k]),l=0,1,2,……,n-12)归一化计算:1/A(k,k)=A(k,k)A(k,j)*A(k,k)=A(k,j),j=1,2,……,n;j≠k3)消元计算A(i,j)-A(i,k)*A(k,j)=A(i,j),i=1,2,……,n;i≠kj=1,2,……,n;j≠k-A(i,k)*A(k,k)=A(i,k),i=1,2,……,n;i≠k4)根据在全选主元过程中所记录的行、列交换的信息进行恢复,恢复的原则:在全选主元过程中,先交换的行(列)后进行恢复;原来的行(列)交换用列(行)交换来恢复。恢复的过程如下:对于k从n-1到0,分别做以下两步:○1A(k,l)A(js[k],l),l=1,2,……,n○2A(l,k)A(l,is[k]),l=1,2,……,n其流程图如下所示:是否图4.1求逆算法流程图矩阵求逆(InverseMatrix函数)全选主元,寻找最大值max=0?A(k,l)A(is[k],l)A(l,k)A(l,js[k])1/A(k,k)=A(k,k)A(k,j)*A(k,k)=A(k,j)输出矩阵不可逆,重新输入A(i,j)-A(i,k)*A(k,j)=A(i,j)-A(i,k)*A(k,k)=A(i,k)A(k,l)A(js[k],l)A(l,k)A(l,is[k])输出逆矩阵(2)矩阵相乘的算法描述如下:首先,i从0到row-1做循环,代表矩阵A的第i行。其次,j从0到row-1做循环,代表矩阵B的第j列。最后,用A的第i行的row个数据乘以矩阵B的第j列中对应的row个数据并求和,作为新矩阵的第i行j列的元素。该算法的流程图如下所示:否是否否是图4.1矩阵乘法流程图矩阵相乘(Cheng函数)i=0irow?j=0jrow?k=0,C(i,j)=0krow?C(i,j)=A(i,k)*B(k,j)k=k+1j=j+1i=i+1输出C(i,j)五、程序设计1.程序设计的基本思路从上面的算法分析可以看到,该问题面临的计算问题的关键是矩阵求逆运算。可以定义一个矩阵类matrix用于存储用户输入的方阵阶数、方阵元素的数据以及方阵的逆矩阵数据,方阵数据用一个一维数组来存放。由于用户需要计算的方阵的阶数大小不一定,因此,用double型指针动态开辟内存的方式来存储用户输入的方阵数据和其逆矩阵的数据。matrix类也定义了构造函数、析构函数、交换等方法,用来实现成员变量的初始化、方阵求逆、两矩阵相乘的操作。矩阵类matrix的功能有设置矩阵的值set_data(),交换两个变量的值swap()、矩阵求逆InverseMatrix()和矩阵相乘Cheng()。程序运行时,运用调用类的方法,首先要求用户输入方阵的阶数,根据该阶数开辟内存空间,接着要求用户输入方阵的数据,输入完毕后,程序调用类的方法用以实现方阵的求逆。在矩阵求逆过程中,要先判断该矩阵是否可逆,若可逆则进行求逆,否则输出提示要求用户重新输入。求出逆矩阵后存储结果并显示,同时对两个矩阵进行相乘操作,用以验证求逆结果的正确性。矩阵类matrix的组成如图5.1所示。martix-row:int-in_bufferdouble*-out_bufferdouble*+matrix()+~martix()+set_data():void+swap(a:double&,b:double&):void+InverseMatrix():int+Cheng():void图5.1matrix类的UML图该程序的主流程图,如图5.2所示。是否图5.2程序流程图输出方阵不可逆,要求重新输入Max=0?调用Cheng函数(计算方阵和其逆矩阵的乘积)调用swap函数(交换两个变量的值)调用InverseMatrix函数(高斯-约当法求逆矩阵)开始结束调用set_data函数(接受用户输入,成员变量赋值输出逆矩阵输出两矩阵相乘的结果2.程序代码及说明//InverseMatrix.cpp:定义控制台应用程序的入口点。#includemath.h#includeiostreamusingnamespacestd;//定义一个类,用于存储方阵数据以及其逆矩阵,并提供求逆的方法和求两矩阵相乘的方法classmatrix{private:introw;//方阵阶数double*in_buffer;//存储输入的矩阵数据double*out_buffer;//存储逆矩阵public:matrix();//构造函数~matrix();//析构函数voidset_data();//用于接收用户输入的函数voidswap(double&a,double&b);//交换两个数据intInverseMatrix();//矩阵求逆voidCheng();//矩阵相乘};matrix::matrix(){row=0;//将方阵阶数初始化为0in_buffer=NULL;//指针指向NULLout_buffer=NULL;}matrix::~matrix(){//如果指针依然指向内存,则将指针指向的内存释放掉,并将指针指向NULLif(in_buffer){delete[]in_buffer;in_buffer=NULL;}if(out_buffer){delete[]out_buffer;out_buffer=NULL;}}/***************************************************函数名称:set_data**函数功能:接收用户的输入的数据,并为成员变量赋值**入口参数:无**出口参数:无*************************************************/voidmatrix::set_data(){inti;cout请输入方阵的阶数endl;cinrow;//如果成员变量指针已经指向了内存,则将指向的内存释放掉并重新分配内存if(in_buffer){delete[]in_buffer;}if(out_buffer){delete[]out_buffer;}in_buffer=newdouble[row*row];out_buffer=newdouble[row*row];cout请输入row*row个数据endl;//输入要分析的方阵的数据,n阶方阵则有n*n个数据for(i=0;irow*row;i++){cinin_buffer[i];}}/**************************************************函数名称:swap**函数功能:交换两个变量的
本文标题:C--课程设计报告
链接地址:https://www.777doc.com/doc-6349671 .html