按照高等代数的传统解法编写c++程序实现N(N<256)元的线性方程组的求解
2016-09-04 16:29
866 查看
对于c++实现线性方程组的求解问题,前辈已经有太多的好算法。有一本书叫《C数值算法》,里面就详尽的论述了如何求解各种各样的线性方程组。
然而,前辈们的算法,无一例外几乎都是只得出一个解。面对奇异线性方程组,也只是尽量化为非奇异的线性方程组,然后解出一种解。
我笨拙,自己想了一套算法,按照高等代数人工求解线性方程组的步骤,用c++模仿人工步骤解决线性方程组的无解、一解、多解问题,并给出一解或者多解的解向量矩阵。
该程序选择从txt文档读入矩阵,并将结果输入txt文档。
(c++处理数据的难点之一,就是对矩阵的运算,实现过程是比较麻烦的。也就是数值运算的困难之处)
然而,前辈们的算法,无一例外几乎都是只得出一个解。面对奇异线性方程组,也只是尽量化为非奇异的线性方程组,然后解出一种解。
我笨拙,自己想了一套算法,按照高等代数人工求解线性方程组的步骤,用c++模仿人工步骤解决线性方程组的无解、一解、多解问题,并给出一解或者多解的解向量矩阵。
该程序选择从txt文档读入矩阵,并将结果输入txt文档。
(c++处理数据的难点之一,就是对矩阵的运算,实现过程是比较麻烦的。也就是数值运算的困难之处)
#include<iostream> #include<fstream> #include<cmath> using namespace std; void solution1(double [][256],int,int,string); void solution2(double [][256],int,int,string); int main() { int end; while(true) { cout<<"请您先在此程序所在文件目录下建立一个txt文档,文档名格式为xxx.txt"<<endl; cout<<"并且将您所要求的线性方程组的系数矩阵(或增广矩阵)整齐的输入进去"<<endl; cout<<"等您完全输入进去并且保存之后,我们再来进行接下来的工作.我等着您哦"<<endl; system("pause"); cout<<"您回来了?看样子你已经输入完毕了.那我们进行接下来的工作吧"<<endl; system("pause"); cout<<"请您输入您刚刚创立的txt文档名"<<endl; string filename; cin>>filename; cout<<"开始解线性方程组了哦"<<endl; int row,column; double matrix[256][256]; cout<<"请您输入线性方程组的系数矩阵(或者非齐次线性方程组的增广矩阵)的行数和列数"<<endl; cin>>row; cin>>column; ifstream infile; infile.open(filename.c_str()); if(!infile.is_open()) { cerr<<"啊哦,出错啦.您是不是把文档名输错啦???哎!没办法啦,关闭程序从头开始吧"<<endl; } else { for(int i=0;i<row;i++) { for(int j=0;j<column;j++) { infile>>matrix[i][j]; } } } infile.close(); system("pause"); int linequ;//linequ==linear equations cout<<"如果该方程组是齐次线性方程组,请您输入1"<<endl; cout<<"如果该方程组是非齐次线性方程组,请您输入2"<<endl; cout<<"您输入的是:"; cin>>linequ; if(linequ==1) { solution1(matrix,row,column,filename); } if(linequ==2) { solution2(matrix,row,column,filename); } if(linequ!=1&&linequ!=2) { cout<<"不按要求来输入,您不乖,我不要和你玩了"<<endl; } system("pause"); cout<<"如果您还想继续求解另一个线性方程组,请输入除666以外的任意整数"<<endl; cout<<"如果您想结束该程序了,请输入666"<<endl; cin>>end; if(end==666) { break; } } return 0; } //定义求解齐次线性方程组的函数 void solution1(double a[][256],int x,int y,string filename) { ofstream outfile; outfile.open(filename.c_str(),ios::app); if(!outfile.is_open()) { cerr<<"啊哦,出错啦!结束程序从头开始吧"<<endl; } //输出线性方程组的系数矩阵 cout<<"********************************************************************************"<<endl; outfile<<endl; outfile<<"您输入的系数矩阵为:"<<endl; for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { outfile<<a[i][j]<<"\t"; } outfile<<endl; } cout<<"您输入的系数矩阵为:"<<endl; for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { cout<<a[i][j]<<"\t"; } cout<<endl; } cout<<"********************************************************************************"<<endl; outfile<<"该系数矩阵的初次行阶梯矩阵为:"<<endl; cout<<"该系数矩阵的初次行阶梯矩阵为:"<<endl; //将系数矩阵化为行阶梯矩阵 int j,k=0;//j作为循环时矩阵列的变量,k作为循环时矩阵行的变量 for(j=0;j<y;j++) { //对矩阵进行冒泡排序,按每列从大到小的顺序排列 for(int i=k;i<x;i++) { for(int i=k;i<x;i++) { if(fabs(a[i][j])<fabs(a[i+1][j])) { for(int j=0;j<y;j++) { double temp; temp=a[i+1][j]; a[i+1][j]=a[i][j]; a[i][j]=temp; } } } } //一行一行的化为行阶梯矩阵 for(int i=k+1;i<x;i++) { if(a[i][j]!=0) { double times; times=a[i][j]/a[k][j]; for(int j=0;j<y;j++) { a[i][j]=a[i][j]-a[k][j]*times; } } else { int sum=0; for(int p=0;p<x;p++) { if(a[p][j]==0) { sum+=1; } } if(sum==2) { int temp=0; for(int j=0;j<y;j++) { if(a[i][j]==0) { temp+=1; } } if(temp!=y) { double times; times=a[i][temp]/a[i-1][temp]; for(int j=0;j<y;j++) { a[i][j]=a[i][j]-a[k][j]*times; } } } } } k+=1; } //输出初次化为的行阶梯矩阵 for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { outfile<<a[i][j]<<"\t"; } outfile<<endl; } for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { cout<<a[i][j]<<"\t"; } cout<<endl; } cout<<"********************************************************************************"<<endl; outfile<<"对初次行阶梯矩阵进行数据调整之后的二次行阶梯矩阵为:"<<endl; cout<<"对初次行阶梯矩阵进行数据调整之后的二次行阶梯矩阵为:"<<endl; //对初次行阶梯矩阵进行数据调整,减小误差 for(int i=0;i<x;i++) for(int j=0;j<y;j++) { if(fabs(a[i][j])<=1e-10) { a[i][j]=0; } } //输出调整之后的行阶梯矩阵 for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { outfile<<a[i][j]<<"\t"; } outfile<<endl; } for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { cout<<a[i][j]<<"\t"; } cout<<endl; } cout<<"********************************************************************************"<<endl; //求出系数矩阵的秩并输出 int r=0; for(int i=0;i<x;i++) { int num=0; for(int j=0;j<y;j++) { if(a[i][j]==0) { num+=1; } } if(num==y) { r+=1; } } r=x-r; outfile<<"二次行阶梯矩阵的秩为:"<<r<<endl; cout<<"二次行阶梯矩阵的秩为:"<<r<<endl; cout<<"********************************************************************************"<<endl; if(r==y) { outfile<<"该线性方程组仅有零解"<<endl; cout<<"该线性方程组仅有零解"<<endl; } if(r<y) { outfile<<"该线性方程组有非零解"<<endl; outfile<<"其解向量构成的矩阵为:"<<endl; cout<<"该线性方程组有非零解"<<endl; cout<<"其解向量构成的矩阵为:"<<endl; //利用行阶梯矩阵求解线性方程组的解向量并输出 int t; double d[y][r];//该数组存储解向量 for(t=0;t<r;t++) { for(int j=0;j<y;j++) { d[j][t]=0; } d[y-1-t][t]=1; for(int p=r-1;p>=0;p--) { double value=0; int num=0; for(int m=0;m<y;m++) { if(a[p][m]==0) { num+=1; } if(a[p][m]!=0) { break; } } for(int q=y-1;q>=num+1;q--) { value+=a[p][q]*d[q][t]; } d[num][t]=(-value)/a[p][num]; } } for(int i=0;i<y;i++) { for(int j=0;j<r;j++) { outfile<<d[i][j]<<"\t"; } outfile<<endl; } for(int i=0;i<y;i++) { for(int j=0;j<r;j++) { cout<<d[i][j]<<"\t"; } cout<<endl; } cout<<"********************************************************************************"<<endl; } outfile.close(); } //定义求解非齐次线性方程组的函数 void solution2(double a[][256],int x,int y,string filename) { ofstream outfile; outfile.open(filename.c_str(),ios::app); if(!outfile.is_open()) { cerr<<"啊哦,出错啦!结束程序从头开始吧"<<endl; } //输出线性方程组的增广矩阵 cout<<"********************************************************************************"<<endl; outfile<<"您输入的增广矩阵为:"<<endl; cout<<"您输入的增广矩阵为:"<<endl; for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { outfile<<a[i][j]<<"\t"; } outfile<<endl; } for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { cout<<a[i][j]<<"\t"; } cout<<endl; } cout<<"********************************************************************************"<<endl; outfile<<"该增广矩阵的初次行阶梯矩阵为:"<<endl; cout<<"该增广矩阵的初次行阶梯矩阵为:"<<endl; //将增广矩阵化为行阶梯矩阵 int j,k=0;//j作为循环时矩阵列的变量,k作为循环时矩阵行的变量 for(j=0;j<y;j++) { //对矩阵进行冒泡排序 for(int i=k;i<x;i++) { for(int i=k;i<x;i++) { if(fabs(a[i][j])<fabs(a[i+1][j])) { for(int j=0;j<y;j++) { double temp; temp=a[i+1][j]; a[i+1][j]=a[i][j]; a[i][j]=temp; } } } } //一行一行的化为行阶梯矩阵 for(int i=k+1;i<x;i++) { if(a[i][j]!=0) { double times; times=a[i][j]/a[k][j]; for(int j=0;j<y;j++) { a[i][j]=a[i][j]-a[k][j]*times; } } else { int sum=0; for(int p=0;p<x;p++) { if(a[p][j]==0) { sum+=1; } } if(sum==2) { int temp=0; for(int j=0;j<y;j++) { if(a[i][j]==0) { temp+=1; } } if(temp!=y) { double times; times=a[i][temp]/a[i-1][temp]; for(int j=0;j<y;j++) { a[i][j]=a[i][j]-a[k][j]*times; } } } } } k+=1; } //输出初次化为的行阶梯矩阵 for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { outfile<<a[i][j]<<"\t"; } outfile<<endl; } for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { cout<<a[i][j]<<"\t"; } cout<<endl; } cout<<"********************************************************************************"<<endl; outfile<<"对初次行阶梯矩阵进行数据调整之后的二次行阶梯矩阵为:"<<endl; cout<<"对初次行阶梯矩阵进行数据调整之后的二次行阶梯矩阵为:"<<endl; //对初次行阶梯矩阵进行数据调整,减小误差 for(int i=0;i<x;i++) for(int j=0;j<y;j++) { if(fabs(a[i][j])<=1e-10) { a[i][j]=0; } } //输出调整之后的行阶梯矩阵 for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { outfile<<a[i][j]<<"\t"; } outfile<<endl; } for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { cout<<a[i][j]<<"\t"; } cout<<endl; } cout<<"********************************************************************************"<<endl; //求出增广矩阵和系数矩阵的秩并输出 int r=0,R=0; for(int i=0;i<x;i++) { int num=0; for(int j=0;j<y;j++) { if(a[i][j]==0) { num+=1; } } if(num==y) { r+=1; } } for(int i=0;i<x;i++) { int num=0; for(int j=0;j<y-1;j++) { if(a[i][j]==0) { num+=1; } } if(num==y-1) { R+=1; } } r=x-r; R=x-R; outfile<<"二次行阶梯矩阵的秩为:"<<r<<endl; cout<<"二次行阶梯矩阵的秩为:"<<r<<endl; cout<<"********************************************************************************"<<endl; if(r<R) { outfile<<"该线性方程组无解"<<endl; cout<<"该线性方程组无解"<<endl; cout<<"********************************************************************************"<<endl; } if(r==R&&r<=y) { outfile<<"该线性方程组有多解"<<endl; outfile<<"其解向量构成的矩阵为:"<<endl; cout<<"该线性方程组有多解"<<endl; cout<<"其解向量构成的矩阵为:"<<endl; //利用行阶梯矩阵求解线性方程组的解向量并输出 int t; double d[y-1][r]; for(t=0;t<r;t++) { for(int j=0;j<y-1;j++) { d[j][t]=0; } d[y-2-t][t]=1; for(int p=r-1;p>=0;p--) { double value=0; int num=0; for(int m=0;m<y-1;m++) { if(a[p][m]==0) { num+=1; } if(a[p][m]!=0) { break; } } for(int q=y-2;q>=num+1;q--) { value+=a[p][q]*d[q][t]; } d[num][t]=(-value)/a[p][num]; } } for(int i=0;i<y-1;i++) { for(int j=0;j<r;j++) { outfile<<d[i][j]<<"\t"; } outfile<<endl; } for(int i=0;i<y-1;i++) { for(int j=0;j<r;j++) { cout<<d[i][j]<<"\t"; } cout<<endl; } cout<<"********************************************************************************"<<endl; outfile<<"其特解的解向量为:"<<endl; cout<<"其特解的解向量为:"<<endl; //利用行阶梯矩阵求解线性方程组的特解 double c[r],e[y-1]; for(int i=0;i<r;i++) { c[i]=a[i][y-1]; } for(int i=0;i<y-1;i++) { e[i]=0; } e[y-2]=1; for(int p=r-1;p>=0;p--) { double value=0; int num=0; for(int m=0;m<y-1;m++) { if(a[p][m]==0) { num+=1; } if(a[p][m]!=0) { break; } } for(int q=y-2;q>=num+1;q--) { value+=a[p][q]*e[q]; } e[num]=(c[p]-value)/a[p][num]; } for(int i=0;i<y-1;i++) { outfile<<e[i]<<"\t"; } for(int i=0;i<y-1;i++) { cout<<e[i]<<"\t"; } cout<<endl; cout<<"********************************************************************************"<<endl; } if(r==R&&r==y) { outfile<<"该线性方程组有唯一解"<<endl; outfile<<"该唯一解的解向量为:"<<endl; cout<<"该线性方程组有唯一解"<<endl; cout<<"该唯一解的解向量为:"<<endl; double m[r],n[y-1]; for(int i=0;i<r;i++) { m[i]=a[i][y-2]; } for(int i=0;i<y-1;i++) { n[i]=0; } n[y-2]=1; for(int p=r-1;p>=0;p--) { double value=0; int num=0; for(int i=0;i<y-1;i++) { if(a[p][i]==0) { num+=1; } if(a[p][i]!=0) { break; } } for(int q=y-2;q>=0;q++) { value+=n[q]*a[p][q]; } n[num]=(m[p]-value)/a[p][num]; } for(int i=0;i<y-1;i++) { outfile<<n[i]<<"\t"; } for(int i=0;i<y-1;i++) { cout<<n[i]<<"\t"; } cout<<endl; cout<<"********************************************************************************"<<endl; } outfile.close(); }
相关文章推荐
- 从易到难编写C++程序,(6)问题:利用问题(5)的随机数生成实现发牌
- 各种线性方程组求解算法的C++实现
- 用C++编写函数判别一个数是否是质数,在主程序中实现输入输出
- 矩阵的LU分解求解线性方程组(C++实现)
- 从易到难编写C++程序,(7)问题:利用问题(6)的发牌,实现24点游戏
- 从易到难编写C++程序,(3)问题:实现一个复杂的猜数字游戏
- 平方根法求解线性方程组(C++实现)
- 编写一个函数,实现把C/C++程序代码中的注释去掉,并把结果返回。
- 数值分析 jacobi迭代法求解线性方程组 MATLAB程序实现
- C++程序的编写和实现
- C++程序的编写和实现
- 从易到难编写C++程序,(4)问题:实现一个大整数表示的BigInt类
- 编写高质量代码之改善C++程序语法篇2<从C到C++需要做的改变>
- C++程序的编写和实现
- 【C++】按照下图的类层次要求编写程序【原创技术】
- 线性方程组求解的几种常用方法-c++代码实现
- 用C++编写递归函数GetPower(int x,int y)计算x的y次幂,在同一程序里中针对整型和实型实现两个重载的函数;在主程序中实现输入输出
- 高等代数第1章 线性方程组的解法
- 编写高质量代码之改善C++程序语法篇3<内存管理 >
- 【C++】按照下图的类层次要求编写程序【原创技术】