北航研究生数值分析编程大作业1.docx
- 文档编号:8115519
- 上传时间:2023-01-28
- 格式:DOCX
- 页数:22
- 大小:165.47KB
北航研究生数值分析编程大作业1.docx
《北航研究生数值分析编程大作业1.docx》由会员分享,可在线阅读,更多相关《北航研究生数值分析编程大作业1.docx(22页珍藏版)》请在冰豆网上搜索。
北航研究生数值分析编程大作业1
《数值分析》计算实习题目
第一题
姓名:
学号:
学院:
航空科学与工程学院
一、开发平台的选择
本题中选择MicrosoftVisualStudio2008作为开发平台,利用VC++作为开发环境,编了一个基于MFC的程序。
本程序不仅仅是界面不同,编程的思想和运算的速度都有提高。
其优点是通过设计类,将所求数组、精度、带宽等封装为成员变量,将幂法、反幂法、矩阵与向量相乘、求向量的2范数和求条件数等功能封装成类的成员函数这也就是利用了封装性。
在定义类的对象之后可以方便地调用这些成员变量和成员函数。
本程序可以很容易地升级为通用性的程序,用户利用可执行文件只需要输入几个参数就可以运算同一类的任意方程,而用户不用像C语言那样改动源代码。
应用面向对象的编程思想还有一个最大的优点是可扩展性。
想添加或改变功能只需要改动成员函数就行了而不会影响到程序的其他部分。
同时,利用MFC还可以开发出很友好的程序界面。
本次程序的初始化界面如下:
二、算法的设计方案
1、矩阵的存储方案
本矩阵为501阶带状矩阵,要求所有零元素均不存储。
于是仅定义二维数组m_Array[ROW_N][COL_N]来存放矩阵A的压缩矩阵,这样可以节省内存空间。
在窗口初始化的时候就调用类的构造函数对m_Array[ROW_N][COL_N]进行初始化。
虽然在程序界面上显示了矩阵,但非零元素其实是没有存储的。
2、求解矩阵的行列式detA
通过doolittle分解,可知
,所以只需将doolittle分解后得到的上三角矩阵U的对角线元素相乘,即可得到行列式A的值。
3、求最小特征值
、最大特征值
和按模最小特征值
通过幂法求解出按模最大的特征值,记为Eigenvalue[0]。
将Eigenvalue[0]作为平移量,调用原点平移函数。
对得到的新矩阵应用幂法,求其按模最大的特征值。
将求出的新特征值加上Eigenvalue[0]后记为Eigenvalue[1]。
比较Eigenvalue[0]与Eigenvalue[1]两个数,较大的数为最大特征值
;较小的数为最小特征值
。
最后通过反幂法计算出按模最小特征值
。
其中求解方程组计算向量
时,先利用已经编好的LU分解法进行分解,再编写回代过程得到u。
4、求A的与数
利用原点平移,设定每次的平移量为
,而后利用反幂法求出相应的
值。
5、求A的(谱范数)条件数
由于A为实对称矩阵,故
,
,所以
6、计算消息的激发
在窗体类中定义一个成员变量m_State,初始化窗体时将它设置为0。
当按下“计算”按钮时激发了按钮被按下的消息,程序开始计算,同时将m_State设为1。
此时再次按下“计算”按钮将弹出提示框“您已经计算过了!
”而不再进行计算了。
这样可以保证计算过程只进行一次。
当输入新的矩阵重新进行计算时,就再次初始化窗口,此时m_State又被初始化为0,可以再次进行计算。
三、源代码
在光盘中有全部的源代码,请用MicrosoftVisualStudio2008打开。
同时还有一个课执行文件可以直接执行。
由于有些程序段是MFC直接生成的,这里没有把那部分程序打出。
1、类的设计
类的头文件为:
#pragmaonce//使头文件只被编译一次
/*常量ROW_N表示压缩矩阵行的维数*/
#defineROW_N5
/*常量COL_N表示压缩矩阵列的维数*/
#defineCOL_N501
classArray//存放所求矩阵A的类。
类的成员函数中定义了对类的基本操作。
{
public:
//声明构造函数和析构函数
Array(void);//默认的构造函数
Array(doublearray);//重载构造函数,使其能对m_Array数组进行针对其他题目的初始化
~Array(void);//默认的析构函数
public:
//声明成员变量
//非零元素压缩存储矩阵
doublem_Array[ROW_N][COL_N];
//中间存储矩阵
doublem_Array_Change[ROW_N][COL_N];
//定义矩阵的上半带宽
intm_s;
//定义矩阵的下半带宽
intm_r;
//定义迭代精度
doublem_Accuracy;
public:
//声明成员函数
//用Doolittle分解法求带状线性方程组的行列式的值
voidDoolittle_LU();
//求三个整形数的最大值
intmax_3(inta,intb,intc);
//对一个向量进行初始化
voidVector_Initialize(doublevector[COL_N]);
//将矩阵恢复到原来的数值
voidRestored();
//取向量的范数
doubleGet_Norm_of_Vector(doublevector[COL_N]);
//计算带状矩阵与列向量的乘积
voidArray_Mul_Vector(doublevector[COL_N],doubleu[COL_N]);
//计算行向量与列向量的乘积
doubleRVector_Mul_CVector(doubleRVector[COL_N],doubleCVector[COL_N]);
//幂法
doublePower_Method();
//原点平移函数
voidOriginMove(doublex);
//反幂法
doubleAntiPower_Method();
//求实对称矩阵的条件数
doubleGet_Spectral_norm(doubleeigenvalue[3]);
};
类的实现文件为:
#include"StdAfx.h"
#include"Array.h"
#include
Array:
:
Array(void)//默认构造函数,针对本问题对压缩数组进行初始化。
{
inti,j;//for循环中用到的循环变量
//输入A的非零元素,存储于矩阵m_Array中,空位由c=0补齐
for(i=0;i for(j=0;j { if(((i==0)&&(j>=2))||((i==4)&&(j<=COL_N-3))) //压缩矩阵的第行前面会有个空位,第行后面会有个空位 { m_Array_Change[i][j]=m_Array[i][j]=-0.064; } elseif(((i==1)&&(j>=1))||((i==3)&&(j<=COL_N-2))) //压缩矩阵的第行前面会有个空位,第行后面会有个空位 { m_Array_Change[i][j]=m_Array[i][j]=0.16; } elseif(i==2)//为主对角线上的元素赋值 { m_Array_Change[i][j]=m_Array[i][j]= (1.64-0.024*(j+1))*sin(0.2*(j+1))-0.64*exp(0.1/(j+1)); } else { m_Array_Change[i][j]=m_Array[i][j]=0; //压缩矩阵中的空位可以用零元素来填充,以免发生内存引用方面的错误 } } m_s=2;//此矩阵的上半带宽为 m_r=2;//此矩阵的下半带宽为 m_Accuracy=1.0e-12;//计算精度 } Array: : ~Array(void) { } Array: : Array(doublearray)//若问题改变可以扩充此重载的构造函数进行初始化 { } voidArray: : Doolittle_LU()//按照教材P26的算法进行计算 { inti,j,k;//循环中用到的循环变量 //做分解A=LU: for(k=1;k<=COL_N;k++)//对k=1,2,...,n执行 { for(j=k;j<=min(k+2,COL_N);j++)//求两个数的最小值可调用已有的函数min { for(i=max_3(1,k-m_r,j-m_s);i<=k-1;i++)//此处的i为教材中的t m_Array[k-j+m_s][j-1]-=m_Array[k-i+m_s][i-1]*m_Array[i-j+m_s][j-1]; } for(j=k+1;(j<=min(k+2,COL_N))&&(k! =COL_N);j++)//此处的j为教材中的i { doublesum=0; for(i=max_3(1,k-m_r,j-m_s);i<=k-1;i++) sum+=m_Array[j-i+m_s][i-1]*m_Array[i-k+m_s][k-1]; m_Array[j-k+m_s][k-1]= (m_Array[j-k+m_s][k-1]-sum)/m_Array[m_s][k-1]; } } } voidArray: : Restored()//将矩阵恢复到原来的数值 { inti,j; for(i=0;i for(j=0;j m_Array[i][j]=m_Array_Change[i][j]; } intArray: : max_3(inta,intb,intc)//求三个数中的最大值 { return(a>max(b,c))? a: max(b,c); } doubleArray: : Get_Norm_of_Vector(doublevector[COL_N])//求向量的范数 { doublesum=0.0; for(inti=0;i { sum+=vector[i]*vector[i]; } returnsqrt(sum); } voidArray: : Array_Mul_Vector(doublevector[COL_N],doubleu[COL_N]) //计算带状矩阵与列向量的乘积 { for(inti=1;i<=COL_N;i++) { doublesum=0.0; for(intj=max(1,i-m_r);j<=min(COL_N,i+m_r);j++) { sum=sum+m_Array[i-j+m_s][j-1]*vector[j-1]; //乘的过程中得把A的坐标转化为C的坐标 } u[i-1]=sum; } } doubleArray: : RVector_Mul_CVector(doubleRVector[COL_N],doubleCVector[COL_N]) { doublesum=0.0; for(inti=0;i { sum+=RVector[i]*CVector[i]; } returnsum; } voidArray: : Vector_Initialize(doublevector[COL_N]) { for(inti=0;i { vector[i]=1; } } doubleArray: : Power_Method()//幂法 { //u为特征向量,uni_u为u的单位化向量 doubleu[COL_N],uni_u[COL_N]; doubleEigenvalue=0.0;//用于存储特征值 doubleEigenvalue_Temp=0.1;//用于比较特征值的变化 doubleNorm_Value;//向量范数的值 Vector_Initialize(u);//对初始向量进行初始化 for(inti=0;fabs(Eigenvalue_Temp-Eigenvalue)/fabs(Eigenvalue)>=m_Accuracy;i++) { Eigenvalue_Temp=Eigenvalue; Norm_Value=Get_Norm_of_Vector(u);//计算向量的范数 for(intj=0;j uni_u[j]=u[j]/Norm_Value; Array_Mul_Vector(uni_u,u);//计算矩阵A与y[k-1]的乘积,得到u[k]存入u中 Eigenvalue=RVector_Mul_CVector(uni_u,u);//计算特征值 } returnEigenvalue; } voidArray: : OriginMove(doublex)//原点平移 { for(inti=0;i m_Array[m_s][i]=m_Array[m_s][i]-x; } doubleArray: : AntiPower_Method()//反幂法 { //u为特征向量,uni_u为u的单位化向量,uni_u_copy为解方程组时用到的向量 doubleu[COL_N],uni_u[COL_N],uni_u_copy[COL_N]; doubleEigenvalue=0.1;//用于存储特征值 doubleEigenvalue_Temp=0.0;//用于比较特征值的变化 doubleNorm_Value;//向量范数的值 doublesum=0.0; Vector_Initialize(u);//对初始向量进行初始化 for(inti=0;fabs(1/Eigenvalue_Temp-1/Eigenvalue) /fabs(1/Eigenvalue)>=m_Accuracy;i++) { Restored(); Eigenvalue_Temp=Eigenvalue; Norm_Value=Get_Norm_of_Vector(u);//计算向量的范数 for(intj=0;j { uni_u[j]=u[j]/Norm_Value; uni_u_copy[j]=uni_u[j]; } Doolittle_LU(); //以下几行是P26页Doolittle分解法的回代过程求解向量u[k] for(inti=2;i<=COL_N;i++) { sum=0.0; for(intt=max(i-m_r,1);t<=i-1;t++) sum+=m_Array[i-t+m_s][t-1]*uni_u_copy[t-1]; uni_u_copy[i-1]-=sum; } u[COL_N-1]=uni_u_copy[COL_N-1]/m_Array[m_s][COL_N-1]; for(inti=COL_N-1;i>=1;i--) { sum=0.0; for(intt=i+1;t<=min(i+m_s,COL_N);t++) sum+=m_Array[i-t+m_s][t-1]*u[t-1]; u[i-1]=(uni_u_copy[i-1]-sum)/m_Array[m_s][i-1]; } Eigenvalue=RVector_Mul_CVector(uni_u,u);//计算特征值 } return1/Eigenvalue; } doubleArray: : Get_Spectral_norm(doubleeigenvalue[3])//求对称矩阵的条件数 { returnfabs(max(fabs(eigenvalue[0]),fabs(eigenvalue[1]))/eigenvalue[2]); } 2、对话框类及算法的驱动函数 因为VC++程序是消息驱动的,真正的主函数是Windows调用的,它的功能是不断地从Windows系统的消息堆栈中读取消息并用消息驱动相应的消息响应函数。 所以在算法这一部分没有主函数,而消息响应函数起到了主函数的作用。 每当我们激发一个消息(比如按下一个按钮)激发的消息将使消息响应函数开始运行,从而进行计算。 窗体类的头文件: //Try_4Dlg.h: 头文件 #pragmaonce #include"afxcmn.h" #include"Array.h" //CTry_4Dlg对话框 classCTry_4Dlg: publicCDialog { //构造 public: CTry_4Dlg(CWnd*pParent=NULL);//标准构造函数 //对话框数据 enum{IDD=IDD_TRY_4_DIALOG}; protected: virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDV支持 //实现 protected: HICONm_hIcon; //生成的消息映射函数 virtualBOOLOnInitDialog(); afx_msgvoidOnSysCommand(UINTnID,LPARAMlParam); afx_msgvoidOnPaint(); afx_msgHCURSOROnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: CListCtrlm_ListCtrl_Result;//显示结果的控件的对象 CListCtrlm_List_Array;//显示矩阵的控件的对象 Arraym_arr;//定义Array类的一个对象 CStringm_Change;//字符转换控件的对象 afx_msgvoidOnBnClickedButtonCul();//“计算”按钮发出的消息的消息响应函数 CStringm_Show_Det;//显示特征值的控件的对象 CStringm_Max_Eigenvalue;//显示最大特征值的控件的对象 CStringm_Show_Min;//显示最小特征值的控件的对象 CStringm_Show_Min_Norm;//显示按模最小特征值的对象 CStringm_Show_Cond;//显示条件数的控件的对象 intm_State;//判断用户是否计算过的记录变量 }; 窗体类的实现文件: //Try_4Dlg.cpp: 实现文件 #include"stdafx.h" #include"Try_4.h" #include"Try_4Dlg.h" #include"Array.h" #include usingnamespacestd; #ifdef_DEBUG #definenewDEBUG_NEW #endif //用于应用程序“关于”菜单项的CAboutDlg对话框 classCAboutDlg: publicCDialog { public: CAboutDlg(); //对话框数据 enum{IDD=IDD_ABOUTBOX}; protected: virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDV支持 //实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg: : CAboutDlg(): CDialog(CAboutDlg: : IDD) {} voidCAboutDlg: : DoDataExchange(CDataExchange*pDX) { CDialog: : DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg,CDialog) END_MESSAGE_MAP() //CTry_4Dlg对话框 CTry_4Dlg: : CTry_4Dlg(CWnd*pParent/*=NULL*/)//窗体的构造函数 : CDialog(CTry_4Dlg: : IDD,pParent) m_Change(_T("")) m_Show_Det(_T("")) m_Max_Eigenvalue(_T("")) m_Show_Min(_T("")) m_Show_Min_Norm(_T("")) m_Show_Cond(_T("")) m_State(0) { m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME); } voidCTry_4Dlg: : DoDataExchange(CDataExchange*pDX) { CDialog: : DoDataExchange(pDX); DDX_Control(pDX,IDC_LIST_RESULT,m_ListCtrl_Result); DDX_Control(pDX,IDC_LIST_ARRAY,m_List_Array); DDX_Text(pDX,IDC_EDIT1,m_Change); DDX_Text(pDX,IDC_EDIT_DET,m_Show_Det); DDX_Text(pDX,IDC_EDIT3,m_Max_Eigenvalue); DDX_Text(pDX,IDC_EDIT2,m_Show_Min); DDX_Text(pDX,IDC_EDIT4,m_Show_Min_Norm); DDX_Text(pDX,IDC_EDIT5,m_Show_Cond); } BEGIN_MESSAGE_MAP(CTry_4Dlg,CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_BUTTON_CUL,&CTry_4Dlg: : OnBnClickedButtonCul) END_MESSAGE_MAP() //CTry_4Dlg消息处理程序 BOOLCTry_4Dlg: : OnInitDialog() { CDialog: : OnInitDialog(); //将“关于...”菜单项添加到系统菜单中。 //IDM_ABOUTBOX必须在系统
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北航 研究生 数值 分析 编程 作业
![提示](https://static.bdocx.com/images/bang_tan.gif)