⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ex_1.cpp

📁 计算方法中列主消元,GUASS法,三角法的算法
💻 CPP
字号:
//求解线性方程组,采用三种方法:Guass消去法、Guass列主元素消去法
// 和直接三角形分解法(Boolittle方法 \ Crout方法)
// 针对课后第五题作个误差分析

#include"stdio.h"
#include"stdlib.h"
#include"math.h"

//求系数矩阵行列式
void det_A(float *A,int n)
{

}

//对增广矩阵(A,b)作一次消元,即(A(row),b(row)) -> (A(row+1),b(row+1))
void CountA_b(float *a,float *b,int row,int n)
{
	int i,j;

	for(i=row+1;i<=n-1;i++)
	{
		for(j=row+1;j<=n-1;j++)
			*(a+i*n+j)=*(a+i*n+j)-*(a+row*n+j)*(*(a+i*n+row))/(*(a+row*n+row));
		*(b+i)=*(b+i)-*(b+row)*(*(a+i*n+row))/(*(a+row*n+row));
	}
}

//使 A(n) 变为上三角矩阵
void Free_A(float *a,int n)
{
	int i,j;

	for(i=1;i<=n-1;i++)
	for(j=0;j<i;j++)
      *(a+i*n+j)=0;
}

//找出从a[row][row]-->a[n-1][row]中最大元素所在行,
//也即第row列中最大元素所在行
int Max_Row(float *a,int row,int n)
{
	int i,max=row;

	for(i=row+1;i<=n-1;i++)
	  if(fabs(*(a+max*n+row))<fabs(*(a+i*n+row))) max=i;

	return max;
}

//交换增广矩阵(A(r),b(r))第 r 行与第 k 行的元素,包括 b 数组
void Exchange_Row(float *a,float *b,int r ,int k,int n)
{
	int j=r;
	float temp;

	for( ;j<=n-1;j++)
	{
	  temp=*(a+r*n+j);*(a+r*n+j)=*(a+k*n+j);*(a+k*n+j)=temp;
	}

	temp=*(b+r);*(b+r)=*(b+k);*(b+k)=temp;
}

//Guass消去法
void Guass(float *a,float *b,int n)
{
	int k;

	for(k=0;k<=n-2;k++)
	{
	  if(*(a+k*n+k)==0) exit(0); //主元素 a[k][k] 不为零
	  CountA_b(a,b,k,n);      //每进行消去一次,判断一次主元素a[k][k]
	}

    //Free_A(a,n);
}

//Guass列主元素消去法
void Guass_Colum(float *a,float *b,int n)
{
	int k,max;

	for(k=0;k<=n-2;k++)
	{
	  if(*(a+k*n+k)==0) exit(0);    //主元素 a[k][k] 不为零
	  max=Max_Row(a,k,n);        //查找最大元素所在的行
	  if(k!=max) Exchange_Row(a,b,k,max,n);
	  CountA_b(a,b,k,n);         //进行消去一次
	}

	//Free_A(a,n);
}

//上三角形回代过程 兼顾 单位上三角形回代
void Return_Top(float *a,float *b,float *x,int n,char p)
{
	int i,j;
	float temp;

	for(i=n-1;i>=0;i--)
	{
	  temp=0;
	  for(j=i+1;j<=n-1;j++)
		temp+=*(a+i*n+j) * (*(x+j));
	  if(p=='Y') *(x+i)=*(b+i)-temp;
	   else *(x+i)=(*(b+i)-temp)/(*(a+i*n+i));
	}
}

//下三角形回代过程 兼顾 单位下三角形回代
void Return_Bottom(float *a,float *b,float *x,int n,char p)
{
	int i,j;
	float temp;

	for(i=0;i<=n-1;i++)
	{
		temp=0;
		for(j=0;j<=i-1;j++)
		  temp+=*(a+i*n+j)*(*(x+j));
		if(p=='Y') *(x+i)=*(b+i)-temp;
		else *(x+i)=(*(b+i)-temp)/(*(a+i*n+i));
	}
}

//直接三角形分解法中Boolittle方法
void Doolittle(float *a,float *LU,int n)
{
	int i,k,p;
	float temp;

	for(k=0;k<=n-1;k++)
	{
		for(i=k;i<=n-1;i++)
		{
			temp=0;
			for(p=0;p<=k-1;p++)
				temp+=*(LU+k*n+p)*(*(LU+p*n+i));
			*(LU+k*n+i)=*(a+k*n+i)-temp;
		}

		for(i=k+1;i<=n-1 && k!=n-1;i++)
		{
			temp=0;
			for(p=0;p<=k-1;p++)
				temp+=*(LU+i*n+p)*(*(LU+p*n+k));
			*(LU+i*n+k)=(*(a+i*n+k)-temp)/(*(LU+k*n+k));
		}
	}
}

//直接三角形分解法中Crout方法
void Crout(float *a,float *LU,int n)
{
	int i,k,p;
	float temp;

	for(k=0;k<=n-1;k++)
	{
	    for(i=k;i<=n-1;i++)
		{
			temp=0;
			for(p=0;p<=k-1;p++)
			temp+=*(LU+i*n+p)*(*(LU+p*n+k));
			*(LU+i*n+k)=*(a+i*n+k)-temp;
		}

		for(i=k+1;i<=n-1 && k!=n-1;i++)
		{
			temp=0;
			for(p=0;p<=k-1;p++)
			temp+=*(LU+k*n+p)*(*(LU+p*n+i));
			*(LU+k*n+i)=(*(a+k*n+i)-temp)/(*(LU+k*n+k)); 
		}
	}
}

//为系数矩阵 A 申请空间
float* MallocSpace_A(int n)
{
	float *base;
	base=(float *)malloc(n*n*sizeof(float));

	return base;
}

//为系数矩阵 b 申请空间
float* MallocSpace_b(int n)
{
	float *base;
	base=(float *)malloc(n*sizeof(float));

	return base;
}

//为分解的上、下三角形矩阵 LU 申请空间
float* MallocSpace_LU(int n)
{
	float *base;
	base=(float *)malloc(n*n*sizeof(float));

	return base;
}

//为解 X 申请空间
float* MallocSpace_X(int n)
{
	float *base;
	base=(float *)malloc(n*sizeof(float));

	return base;
}

//为解 Std_X 申请空间
float* MallocSpace_Std_X(int n)
{
	float *base;
	base=(float *)malloc(n*sizeof(float));

	return base;
}

//为暂存量 Y 申请空间
float* MallocSpace_Y(int n)
{
    float *base;
	base=(float *)malloc(n*sizeof(float));

	return base;
}

//输入系数矩阵和常量矩阵
void InputElement(float *a1,float *b1,float *std_x,int n)
{
	int i,j;
	float temp;

	printf("输入系数矩阵:\n");
	for(i=0;i<=n-1;i++)
	for(j=0;j<=n-1;j++)
    {
		scanf("%f",&temp);
		*(a1+i*n+j)=temp;
	}

	printf("输入常量矩阵:\n");
	for(i=0;i<=n-1;i++)
	{
		scanf("%f",&temp);
		*(b1+i)=temp;
	}

	printf("输入标准的解:\n");
	for(i=0;i<=n-1;i++)
	{
		scanf("%f",&temp);
		*(std_x+i)=temp;
	}
}

//为系数矩阵作个备份
float* Copy_A(float *a1,int n)
{
  int i,j;
  float *base;
  
  base=(float *)malloc(n*n*sizeof(float));

  for(i=0;i<=n-1;i++)
  for(j=0;j<=n-1;j++)
  *(base+i*n+j)=*(a1+i*n+j);

  return base;
}

//为常量矩阵作个备份
float* Copy_b(float *b1,int n)
{
  int i;
  float *base;
  
  base=(float *)malloc(n*sizeof(float));

  for(i=0;i<=n-1;i++)
  *(base+i)=*(b1+i);

  return base;

}

//打印求解线性方程组的系数矩阵
void OutputElement_A(float *A,int n)
{
	int i,j;

	printf("\n此方程组的系数矩阵为:\n");
	for(i=0;i<=n-1;i++)
	{
	  for(j=0;j<=n-1;j++)
	  printf("%f   ",*(A+i*n+j));

	  printf("\n");
	}
}

//打印求解线性方程组的常量矩阵
void OutputElement_b(float *b,int n)
{
	int i;

	printf("\n此方程组的常量矩阵为:\n");
	for(i=0;i<=n-1;i++)
	printf("%f   ",*(b+i));

	printf("\n");

}

//打印求解线性方程组的解
void OutputElement(float *x,int n)
{
	int i;

	printf("\n此方程组的解为:\n");
	for(i=0;i<=n-1;i++)
	printf("%f\n",*(x+i));

}

//为系数矩阵重新赋值
void Give_A(float *a1,float *a2,int n)
{
	int i,j;

	for(i=0;i<=n-1;i++)
	for(j=0;j<=n-1;j++)
	  *(a2+i*n+j)=*(a1+i*n+j);

}

//为常量矩阵重新赋值
void Give_b(float *b1,float *b2,int n)
{
	int i;

	for(i=0;i<=n-1;i++)
	  *(b2+i)=*(b1+i);

}

// 针对课后第五题作个误差分析
void Count_Error(float *x,float *std_x,int n)
{
	int i;
    float temp;

	printf("课后第五题误差分析情况:\n");
    for(i=0;i<n;i++)
	{
      temp=(float)(fabs(*(x+i)-*(std_x+i))/fabs(*(std_x+i)));
	  printf("%.4f",temp*100);
	  putchar('%');        //不能用printf("%");语句
	  printf("   ");
	}
	printf("\n");
}

//选择方法
void Select_Methom(float *a,float *b,float *lu,float *x,float *std_x,float *y,int n)
{
	int select1,select2;

	printf("\n请选择解线性方程组的方法,提示信息如下:\n");
	printf("\n选择 Guass 消去法,          请输入 1\n");
	printf("选择 Guass 列主元素消去法,  请输入 2\n");
	printf("选择 直接三角形分解法,      请输入 3\n");
	printf("选择 退出,                  请输入 4\n");
	printf("\n请选择你所要采用的方法:  ");
	scanf("%d",&select1);

	switch(select1)
	{
	case 1:printf("\n--------------------采用Guass消去法--------------------\n");
		Guass(a,b,n);
		Return_Top(a,b,x,n,'N');
		OutputElement(x,n);
		break;
	case 2:printf("\n--------------------采用Guass列主元素消去法--------------------\n");
		Guass_Colum(a,b,n);
		Return_Top(a,b,x,n,'N');
		OutputElement(x,n);
		break;
    case 3:printf("\n--------------------采用直接三角形分解法--------------------\n");
		printf("请选择分解的方法 :\n");
		printf("选择 Boolittle 方法,请输入 1\n");
		printf("选择 Crout 方法,请输入 2\n");
		printf("采用哪种方法: ");
		scanf("%d",&select2);

		switch(select2)
		{
		case 1:printf("--------------------Bolittle--------------------\n");
			Doolittle(a,lu,n);
			Return_Bottom(lu,b,y,n,'Y');//单位下三角形回代
			Return_Top(lu,y,x,n,'N');
            OutputElement(x,n);
			break;
		case 2:printf("--------------------Crout--------------------\n");
			Crout(a,lu,n);
			Return_Bottom(lu,b,y,n,'N');
			Return_Top(lu,y,x,n,'Y');//单位上三角形回代
			OutputElement(x,n);
			break;
		}
		break;
	case 4:exit(0);
	}
	// 针对课后第五题作个误差分析
    Count_Error(x,std_x,n);
}
  
//主函数
void main()
{
	int n;  
	char flag='Y';   //flag 用来表示求解过程是否要继续,开始为 'Y'
	float *a1,*a2,*b1,*b2;
	float *lu,*x,*std_x,*y;

	printf("----------本程序是用来求解线性方程组的解的!!----------\n");
	printf("请输入求解线性方程组的阶数(n): ");
	scanf("%d",&n);

	a1=MallocSpace_A(n);
	b1=MallocSpace_b(n);
	lu=MallocSpace_LU(n);
	x=MallocSpace_X(n);
	std_x=MallocSpace_Std_X(n);
	y=MallocSpace_Y(n);

	InputElement(a1,b1,std_x,n);

	a2=Copy_A(a1,n);
	b2=Copy_b(b1,n);

	while(flag=='Y')
	{
      Give_A(a1,a2,n);
	  Give_b(b1,b2,n);
	  Select_Methom(a2,b2,lu,x,std_x,y,n);
	  getchar();     //去消输入 n 时,产生的回车符'\n',使scanf()语句不再继续执行
	  printf("\n是否还需须尝试用其它的方法进行求解(Y:继续;任意:退出): ");
      scanf("%c",&flag);
	}
}




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -