• <转>线性方程组求解


    //解线性方程组
    #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;
    }
    
  • 相关阅读:
    hadoop ha模式下,kill active的namenode节点后,standby的namenode节点没能自动启动
    Hadoop2.6.5单机安装
    hadoop HA集群搭建
    hadoop搭建HA集群之后不能自动切换namenode
    hadoop集群之HDFS和YARN启动和停止命令
    查看CentOS7 监听端口命令
    JournalNode的作用
    Secondary NameNode:它究竟有什么作用?
    CentOS7查看和关闭防火墙
    关于Hosts与network的异同之处
  • 原文地址:https://www.cnblogs.com/zhangdongsheng/p/1997082.html
Copyright © 2020-2023  润新知