//解线性方程组 #include<iostream.h> #include<iomanip.h> #include<stdlib.h> //----------------------------------------------全局变量定义区 const int Number=15; //方程最大个数 double a[Number][Number],b[Number],copy_a[Number][Number],copy_b[Number]; //系数行列式 int A_y[Number]; //a[][]中随着横坐标增加列坐标的排列顺序,如a[0][0],a[1][2],a[2][1]...则A_y[]={0,2,1...}; int lenth,copy_lenth; //方程的个数 double a_sum; //计算行列式的值 char * x; //未知量a,b,c的载体 //----------------------------------------------函数声明区 void input(); //输入方程组 void print_menu(); //打印主菜单 int choose (); //输入选择 void cramer(); //Cramer算法解方程组 void gauss_row(); //Gauss列主元解方程组 void guass_all(); //Gauss全主元解方程组 void Doolittle(); //用Doolittle算法解方程组 int Doolittle_check(double a[][Number],double b[Number]); //判断是否行列式>0,若是,调整为顺序主子式全>0 void xiaoqu_u_l(); //将行列式Doolittle分解 void calculate_u_l(); //计算Doolittle结果 double & calculate_A(int n,int m); //计算行列式 double quanpailie_A(); //根据列坐标的排列计算的值,如A_y[]={0,2,1},得sum=a[0][ A_y[0] ] * a[1][ A_y[1] ] * a[2][ A_y[2] ]=a[0][0]*a[1][2]*a[2][1]; void exchange(int m,int i); //交换A_y[m],A_y[i] void exchange_lie(int j); //交换a[][j]与b[]; void exchange_hang(int m,int n); //分别交换a[][]和b[]中的m与n两行 void gauss_row_xiaoqu(); //Gauss列主元消去法 void gauss_all_xiaoqu(); //Gauss全主元消去法 void gauss_calculate(); //根据Gauss消去法结果计算未知量的值 void exchange_a_lie(int m,int n); //交换a[][]中的m和n列 void exchange_x(int m,int n); //交换x[]中的x[m]和x[n] void recovery(); //恢复数据 //主函数 void main() { int flag=1; input(); //输入方程 while(flag) { print_menu(); //打印主菜单 flag=choose(); //选择解答方式 } } //函数定义区 void print_menu() { system("cls"); cout<<"------------方程系数和常数矩阵表示如下:\n"; for(int j=0;j<lenth;j++) cout<<"系数"<<j+1<<" "; cout<<"\t常数"; cout<<endl; for(int i=0;i<lenth;i++) { for(j=0;j<lenth;j++) cout<<setw(8)<<setiosflags(ios::left)<<a[i][j]; cout<<"\t"<<b[i]<<endl; } cout<<"-----------请选择方程解答的方案----------"; cout<<"\n 1. 克拉默(Cramer)法则"; cout<<"\n 2. Gauss列主元消去法"; cout<<"\n 3. Gauss全主元消去法"; cout<<"\n 4. Doolittle分解法"; cout<<"\n 5. 退出"; cout<<"\n 输入你的选择:"; } void input() { int i,j; cout<<"方程的个数:"; cin>>lenth; if(lenth>Number) { cout<<"It is too big.\n"; return; } x=new char[lenth]; for(i=0;i<lenth;i++) x[i]='a'+i; //输入方程矩阵 //提示如何输入 cout<<"====================================================\n"; cout<<"请在每个方程里输入"<<lenth<<"系数和一个常数:\n"; cout<<"例:\n方程:a"; for(i=1;i<lenth;i++) { cout<<"+"<<i+1<<x[i]; } cout<<"=10\n"; cout<<"应输入:"; for(i=0;i<lenth;i++) cout<<i+1<<" "; cout<<"10\n"; cout<<"==============================\n"; //输入每个方程 for(i=0;i<lenth;i++) { cout<<"输入方程"<<i+1<<":"; for(j=0;j<lenth;j++) cin>>a[i][j]; cin>>b[i]; } //备份数据 for(i=0;i<lenth;i++) for(j=0;j<lenth;j++) copy_a[i][j]=a[i][j]; for(i=0;i<lenth;i++) copy_b[i]=b[i]; copy_lenth=lenth; } //输入选择 int choose() { int choice;char ch; cin>>choice; switch(choice) { case 1:cramer();break; case 2:gauss_row();break; case 3:guass_all();break; case 4:Doolittle();break; case 5:return 0; default:cout<<"输入错误,请重新输入:"; choose(); break; } cout<<"\n是否换种方法求解(Y/N):"; cin>>ch; if(ch=='n'||ch=='N') return 0; recovery(); cout<<"\n\n\n"; return 1; } //用克拉默法则求解方程. void cramer() { int i,j;double sum,sum_x;char ch; //令第i行的列坐标为i cout<<"用克拉默(Cramer)法则结果如下:\n"; for(i=0;i<lenth;i++) A_y[i]=i; sum=calculate_A(lenth,0); if(sum!=0) { cout<<"系数行列式不为零,方程有唯一的解:"; for(i=0;i<lenth;i++) { ch='a'+i; a_sum=0; for(j=0;j<lenth;j++) A_y[j]=j; exchange_lie(i); sum_x=calculate_A(lenth,0); cout<<endl<<ch<<"="<<sum_x/sum; exchange_lie(i); } } else { cout<<"系数行列式等于零,方程没有唯一的解."; } cout<<"\n"; } double & calculate_A(int n,int m) //计算行列式 { int i; if(n==1) { a_sum+= quanpailie_A(); } else{for(i=0;i<n;i++) { exchange(m,m+i); calculate_A(n-1,m+1); exchange(m,m+i); } } return a_sum; } double quanpailie_A() //计算行列式中一种全排列的值 { int i,j,l; double sum=0,p; for(i=0,l=0;i<lenth;i++) for(j=0;A_y[j]!=i&&j<lenth;j++) if(A_y[j]>i) l++; for(p=1,i=0;i<lenth;i++) p*=a[i][A_y[i]]; sum+=p*((l%2==0)?(1):(-1)); return sum; } //高斯列主元排列求解方程 void gauss_row() { int i,j; gauss_row_xiaoqu(); //用高斯列主元消区法将系数矩阵变成一个上三角矩阵 for(i=0;i<lenth;i++) { for(j=0;j<lenth;j++) cout<<setw(10)<<setprecision(5)<<a[i][j]; cout<<setw(10)<<b[i]<<endl; } if(a[lenth-1][lenth-1]!=0) { cout<<"系数行列式不为零,方程有唯一的解:\n"; gauss_calculate(); for(i=0;i<lenth;i++) //输出结果 { cout<<x[i]<<"="<<b[i]<<"\n"; } } else cout<<"系数行列式等于零,方程没有唯一的解.\n"; } void gauss_row_xiaoqu() //高斯列主元消去法 { int i,j,k,maxi;double lik; cout<<"用Gauss列主元消去法结果如下:\n"; for(k=0;k<lenth-1;k++) { j=k; for(maxi=i=k;i<lenth;i++) if(a[i][j]>a[maxi][j]) maxi=i; if(maxi!=k) exchange_hang(k,maxi);// for(i=k+1;i<lenth;i++) { lik=a[i][k]/a[k][k]; for(j=k;j<lenth;j++) a[i][j]=a[i][j]-a[k][j]*lik; b[i]=b[i]-b[k]*lik; } } } //高斯全主元排列求解方程 void guass_all() { int i,j; gauss_all_xiaoqu(); for(i=0;i<lenth;i++) { for(j=0;j<lenth;j++) cout<<setw(10)<<setprecision(5)<<a[i][j]; cout<<setw(10)<<b[i]<<endl; } if(a[lenth-1][lenth-1]!=0) { cout<<"系数行列式不为零,方程有唯一的解:\n"; gauss_calculate(); for(i=0;i<lenth;i++) //输出结果 { for(j=0;x[j]!='a'+i&&j<lenth;j++); cout<<x[j]<<"="<<b[j]<<endl; } } else cout<<"系数行列式等于零,方程没有唯一的解.\n"; } void gauss_all_xiaoqu() //Gauss全主元消去法 { int i,j,k,maxi,maxj;double lik; cout<<"用Gauss全主元消去法结果如下:\n"; for(k=0;k<lenth-1;k++) { for(maxi=maxj=i=k;i<lenth;i++) { for(j=k;j<lenth;j++) if(a[i][j]>a[maxi][ maxj]) { maxi=i; maxj=j; } } if(maxi!=k) exchange_hang(k,maxi); if(maxj!=k) { exchange_a_lie(maxj,k); //交换两列 exchange_x(maxj,k); } for(i=k+1;i<lenth;i++) { lik=a[i][k]/a[k][k]; for(j=k;j<lenth;j++) a[i][j]=a[i][j]-a[k][j]*lik; b[i]=b[i]-b[k]*lik; } } } void gauss_calculate() //高斯消去法以后计算未知量的结果 { int i,j;double sum_ax; b[lenth-1]=b[lenth-1]/a[lenth-1][lenth-1]; for(i=lenth-2;i>=0;i--) { for(j=i+1,sum_ax=0;j<lenth;j++) sum_ax+=a[i][j]*b[j]; b[i]=(b[i]-sum_ax)/a[i][i]; } } void Doolittle() //Doolittle消去法计算方程组 { double temp_a[Number][Number],temp_b[Number];int i,j,flag; for(i=0;i<lenth;i++) for(j=0;j<lenth;j++) temp_a[i][j]=a[i][j]; flag=Doolittle_check(temp_a,temp_b); if(flag==0) cout<<"\n行列式为零.无法用Doolittle求解."; xiaoqu_u_l(); calculate_u_l(); cout<<"用Doolittle方法求得结果如下:\n"; for(i=0;i<lenth;i++) //输出结果 { for(j=0;x[j]!='a'+i&&j<lenth;j++); cout<<x[j]<<"="<<b[j]<<endl; } } void calculate_u_l() //计算Doolittle结果 { int i,j;double sum_ax=0; for(i=0;i<lenth;i++) { for(j=0,sum_ax=0;j<i;j++) sum_ax+=a[i][j]*b[j]; b[i]=b[i]-sum_ax; } for(i=lenth-1;i>=0;i--) { for(j=i+1,sum_ax=0;j<lenth;j++) sum_ax+=a[i][j]*b[j]; b[i]=(b[i]-sum_ax)/a[i][i]; } } void xiaoqu_u_l() //将行列式按Doolittle分解 { int i,j,n,k;double temp; for(i=1,j=0;i<lenth;i++) a[i][j]=a[i][j]/a[0][0]; for(n=1;n<lenth;n++) { //求第n+1层的上三角矩阵部分即U for(j=n;j<lenth;j++) { for(k=0,temp=0;k<n;k++) temp+=a[n][k]*a[k][j]; a[n][j]-=temp; } for(i=n+1;i<lenth;i++) //求第n+1层的下三角矩阵部分即L { for(k=0,temp=0;k<n;k++) temp+=a[i][k]*a[k][n]; a[i][n]=(a[i][n]-temp)/a[n][n]; } } } int Doolittle_check(double temp_a[][Number],double temp_b[Number]) //若行列式不为零,将系数矩阵调整为顺序主子式大于零 { int i,j,k,maxi;double lik,temp; for(k=0;k<lenth-1;k++) { j=k; for(maxi=i=k;i<lenth;i++) if(temp_a[i][j]>temp_a[maxi][j]) maxi=i; if(maxi!=k) { exchange_hang(k,maxi); for(j=0;j<lenth;j++) { temp=temp_a[k][j]; temp_a[k][j]=temp_a[maxi][j]; temp_a[maxi][j]=temp; } } for(i=k+1;i<lenth;i++) { lik=temp_a[i][k]/temp_a[k][k]; for(j=k;j<lenth;j++) temp_a[i][j]=temp_a[i][j]-temp_a[k][j]*lik; temp_b[i]=temp_b[i]-temp_b[k]*lik; } } if(temp_a[lenth-1][lenth-1]==0) return 0; return 1; } void exchange_hang(int m,int n) //交换a[][]中和b[]两行 { int j; double temp; for(j=0;j<lenth;j++) { temp=a[m][j]; a[m][j]=a[n][j]; a[n][j]=temp; } temp=b[m]; b[m]=b[n]; b[n]=temp; } void exchange(int m,int i) //交换A_y[m],A_y[i] { int temp; temp=A_y[m]; A_y[m]=A_y[i]; A_y[i]=temp; } void exchange_lie(int j) //交换未知量b[]和第i列 { double temp;int i; for(i=0;i<lenth;i++) { temp=a[i][j]; a[i][j]=b[i]; b[i]=temp; } } void exchange_a_lie(int m,int n) //交换a[]中的两列 { double temp;int i; for(i=0;i<lenth;i++) { temp=a[i][m]; a[i][m]=a[i][n]; a[i][n]=temp; } } void exchange_x(int m,int n) //交换未知量x[m]与x[n] { char temp; temp=x[m]; x[m]=x[n]; x[n]=temp; } void recovery() //用其中一种方法求解后恢复数据以便用其他方法求解 { for(int i=0;i<lenth;i++) for(int j=0;j<lenth;j++) a[i][j]=copy_a[i][j]; for(i=0;i<lenth;i++) b[i]=copy_b[i]; for(i=0;i<lenth;i++) x[i]='a'+i; a_sum=0; lenth=copy_lenth; }