线性方程组求解

简介:
//解线性方程组
#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;
}
相关文章
|
小程序 数据安全/隐私保护 Android开发
八米云-N1盒子、机顶盒等设备-小白保姆式超详细刷机教程
这里以魔百盒CM211-1为例,本次刷机用到的零碎工具比较多,不过都是常见刚需设备,大家可以按照清单核对一下。 目前只支持S905 L3、L3a、L2 系列的各种盒子
1633 1
八米云-N1盒子、机顶盒等设备-小白保姆式超详细刷机教程
|
安全 数据安全/隐私保护 芯片
微信读书电脑版,来了!
微信读书电脑版,来了!
|
JSON API 定位技术
AppFlow:让通义千问大模型调用你的任意API
在阿里云AppFlow中,通过自定义插件连接器可使通义千问获取特定功能,如旅游规划或投资辅助。登录AppFlow控制台,选择“自定义连接器”,上传图标,设定基本信息,选“插件连接器”。支持Basic、Bearer Token、AppCode等鉴权。精确配置API名称、描述及请求参数,确保模型调用准确。参考示例curl命令调整参数结构,填写响应体帮助模型解析。发布后,在模型Agent搭建中选用自定义连接器增强功能。
13484 7
|
机器学习/深度学习 NoSQL Redis
Redis -- zset有序集合
Redis -- zset有序集合
276 0
|
Linux 开发工具
【专栏】Linux 必备技能:Vim文本编辑器中快速跳转到文件开头和结尾的方法
【4月更文挑战第28天】本文介绍了Vim文本编辑器中快速跳转到文件开头和结尾的方法。使用`gg`或`1G`可跳转到文件开头,`G`或`$`则用于跳转到结尾。此外,还提到了跳转到指定行(如`10G`)和查找特定字符(如`f`+字符)的技巧,以提升编辑效率。
2230 0
|
机器学习/深度学习 自然语言处理
社区供稿 | EcomGPT:基于任务链数据的电商大模型(附魔搭推理实践)
在电商领域中,自然语言处理和深度学习的发展对电商技术的推进做出了很大的贡献。通过这些技术,可以实现从产品信息提取到用户查询理解等多种能力,尤其是近期各类大语言模型(Large Language Models,LLMs)的涌现,让我们看到了它们在电商领域引用的潜力。然而,通用的大语言模型并不是专门为电商领域设计的,这可能导致它们在电商任务中表现不佳。
|
网络安全 数据安全/隐私保护
银河麒麟v10系统SSH远程管理及切换root用户的操作方法
银河麒麟v10系统SSH远程管理及切换root用户的操作方法
5792 0
|
缓存 C语言
C语言——数据的输入输出
C语言——数据的输入输出
|
弹性计算 网络协议 安全
阿里云ECS云服务器安全组设置开放端口教程
阿里云ECS云服务器安全组设置开放端口教程,阿里云服务器端口怎么打开?云服务器ECS端口在安全组中开启,轻量应用服务器端口在防火墙中打开,阿里云服务器网以80端口为例,来详细说下阿里云服务器端口开放图文教程,其他的端口如8080、3306、443、1433也是同样的方法进行开启端口:
2164 0