数值计算线性方程组求解实现

一、引言

在自然科学和工程技术中很多问题的解决常常归结为解线性代数方程组,从而获得问题的解决方案,在解方程组的过程中从大的方面来讲有直接法和迭代法。而以下我们的程序通过高斯消去法和三角分解法解线性方程组中,主要是运用了迭代法。

二、算法描述(Linear equation

1Guass elimination

1n,m分别表示线性方程组的个数和所要求解未知量的个数,函数中设置变量root_number,监视方程组解的个数,具体对应关系如下表所示(斜杠表示不存在的情况)

 root_number

n>m

n=m

n

0

线性方程组无解

1

方程组个数大于未知数个数,但有些项可以消去,有唯一一组解

方程组个数等于未知数个数,有唯一一组解

IF(表示无穷大)

方程组个数大于未知数个数,但有些项可以消去,有无穷多组解

方程组个数等于未知数个数,但有些项可以消去,有无穷多组解

方程组个数小于未知数个数,有无穷多组解

这里具体以n=m讨论且没有可以消去的项,

具体如下矩阵,设有n元矩阵m个未知量

a11  · · ·   a1m         x1  b1    

· ·        ·    ·     ·

·    ·     ·    ·  = ·

·      ·   ·    ·     ·

an1  · · ·      anm        xn              bn

已知矩阵中m+1列存放方程结果b1,b2,…bn

第一步:选取第一列中ai1绝对值最大的作为主元,即主元所在行与第一行交换,

然后 令

li1= ai1/a11,i= 2,3,……,m+1

用(-li1)乘第一个方程加到第i个方程上,得同解方程组:

a11(1)   a11(1)  ·   a1m(1)          x1        b1(1)

0     a22(2)   ·   a2m(2)      x2         b2(2)

  ·    ·     ·   ·        ·   =    ·

  0      an-12(1)  ·  an-1m(1)        xn-1           bn-1(2)

0     an2(1)   ·    anm (1)        xn             bn(2)

简记为A(2)*X=b(2),其中

aij(2) = aij(1) – li1 * a1j(1) ,  i=2,3….n,   j = 2,3,..,m+1

第二步:如果a22(2) != 0,令 li2= ai2(2/a22(2, I= 3,……,n 依据同样的原理,对矩阵进行化间(省略),依次下去,直到完成!

最后得到矩阵方程

1   a12(1) ·  ·   a1m(1)          x1        b1(1)

0   1    ·  ·   a2m(2)      x2        b2(2)

  0   0    ·  ·   ·       ·   =   ·

               1      an-1m (n-1)      xn-1          bn-1(n-1)

0   0    0    ·      1             xn             bn(n)

简记为 A(n)*x=b(n)

线性方程组的结果(即b值)存储在数组最后一列,

则求解过程如下:

Xn=an,n+1

Xn-1=a n-1,n+1-an-1,n*xn

Xn-2=an-2,n+1-an-2,n-1*xn-1-an-2,n*xn

X1=a1,n+1-a1,2*x2-a1,3*x3-…-a1,n*xn

2LU  factorisation

输入线性方程组的个数n和未知量m的个数,若n不等于m。则不满足分解条件,无法分解。下面只讨论n等于m的情况。

同样设置一个二维数组存放系数和结果

具体矩阵如下

a11    a 12  …  a1n          1                     u11  u12  …    u1n     

a21    a22    … a2n        l21   1                       u22  …    u2n      

A=   …    …     …  =                              

an1    an2   …  ann         ln1   ln2 … 1                unn

有矩阵乘法及矩阵相等知识可得

a1j=u1j,j=1,2…n

       ∑lipupj,    j

Aij=   

       ∑lipupj+uij   j>=i

有此得到计算lij和uij的递推公式

(1)u1j, = a1j  j=1,2,3..n;  li1=ai1/u11   i=2,3,…n     2-1

下面计算U的第k行,L的第k列元素  k=2,3,4…n

(2)                  ( j=k,k+1…n)   2-2

(3)                          (i=k+1,…n;且  kn)   2-3

(4)lkk=1   2-4

按照(2-1-2-4)式,计算的顺序如下,即重第一行到第n行,每


一行都是从左到右依次计算:

u11   u12   u13   …    u1n

l21    u22    u23   …   u2n

l31     l32   u33   …   u3n

…    …           … 

ln1     ln2  …   ln.n-1    unn

矩阵A=LU分解后,结果代入

Ly=b

Ux=y

即可求解方程组的解,

Ly=b

Ux=y

即求出先行矩阵的解!

四、特色

      1.双重指针

        两种方法均用双重指针(即指向指针的指针)

     double **linear=(double **)malloc(dem*sizeof(double));此处linear相当于指针数组名,用指针模拟数组;

      linear[i]=(double *)malloc((dem+1)*sizeof(double));具体成员为一指向一维数组的指针。

     由用户输入的维数和列数动态申请存储空间,避免宏定义大数组所导致的存储空间的过度占用,。

     2.合理行翻转

      当对角线上的元素较小时,若不进行翻转,可能导致中间过程得到很大的数,超出计算机大存储范围从而出错,我们组通过行翻转,即每次找出当前列中最大的元素,将当前列中绝对值最大的元素所在行(linear[max_index]指向的行)与本行(linear[k]指向的行)交换。由于采用指针数组,故只需交换linear[max_index]

与linear[k]的内容。

      具体代码:

    int max_index=k;

for(i=k;i

{

if(fabs(linear[i][k])>fabs(linear[max_index][k]))

max_index=i;

}

       if(k!=max_index)

       {

double *p=linear[k];

linear[k]=linear[max_index];

linear[max_index]=p;

       }

      3.程序健壮性

       31、高斯消元法

       对于高斯消元法,我们基本实现了所有线性方程组的求解,(用n表示行数,m表示列数),公分三种情况:

       (1)、n即方程个数小于未知数的个数

       (2)、n=m即方程个数等于未知数的个数

       (3)、n>m即方程个数大于未知数的个数

      其中每种情况都可能出现有无穷解,有唯一解,无解三种情况(n时不可能出现无穷解,排除此种情况),这3*3-1=8情况都可以在高斯消元法基本思想的前提下通过增加判断条件完成。

       具体说来就是在每阶段完成后判断有无某行系数和结果都为零或某行系数为零但结果不为零

   A.某阶段完成后,进行判断

   B.若出现某行系数为零但结果不为零,不管非零行个数(记作temp_n)与列数m的关系如何,必定无穷解,令root_number=0,退成本次求解,输出无解提示。

   C.若出现某行系数和结果都为零,则将其与最后一个非零行互换,temp_n=temp_n-1(此处temp_n用来控制循环的,temp_n=temp_n-1可以有效控制循环次数并防止出现除以0导致出错)

   D.接着进行下一次转换,然后转入A过程,直到不满足循环条件为止。

a.若root_number!=0且非零行个数temp_n列数),证明有效方程个数小于未知数个数,root_number=IF(无穷大标志),有无穷解。

b.若root_number!=0且非零行个数temp_n=m(列数),证明有效方程个数等于未知数个数,root_number=1,有唯一解。

c.若root_number=0,无解

每种情况都有具体的提示信息。(此处鹤哥可以演示一下程序)

    3-2矩阵LU解法

由于LU分解法只能解较为特殊的方阵,即所输入矩阵的行列相等,而且各阶顺序主子式不为0,所以我们组的程序首先根据输入判断是否符合条件,即编写求顺序主子式的函数,符合条件者再才进行LU分解。

     n阶方阵 是非奇异方阵的充要条件是 为可逆矩阵,也即A的行列式不为零。

     定理 若A是非奇异矩阵,A能分解为LU的充分必要条件是A的顺序主子式均不为0

    

 为了节省空间,上下三角存于原矩阵,只是下三角对角线上的单独输1

   

   4.我们的程序跟踪了每步的关键结果,便于观察矩阵的化简过程,以较清晰的输入格式展示数据           

      

(让杨林岱做PPT的时候主意,在复制公式和矩阵的时候,有的字和点还有数学符号,有的是截图,有的是文字 )

岱哥,PPT要做的好看啊!特色一定要着重搞啊。图什么的你可以补充,如果你要截图的话,测试数据在(测试数据.txt)中,也可以让鹤哥在讲解的时候粘贴数据演示程序。还有就是老师说PPT开始要把每个人的工作写进去,尽量把每个人都写得干过事,这个可以灵活处理。总结你随便写点东西。如果有动画效果就更好了。

//高斯消元法
#include
#include
#include
using namespace std;
#define IF 1000000//标记解的个数

/定义的全局变量
double root[100];
int n,m;
char varible[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int root_number;

double iteration_root(double **linear,int i)
//迭代法求方程组中第i个未知数的解
{
	if(i==m-1)
		return linear[m-1][m];
	else 
	{
		double sum=linear[i][m];
		for(int j=i;jfabs(linear[max_index][k]))
				max_index=i;
		}
		double *p=linear[k];
		linear[k]=linear[max_index];
		linear[max_index]=p;
		
		对角线上元素为0,无法继续进行下去///
		if(linear[k][k]==0)
		{
			if(k=0;iii--)
					{
						for(jjj=0;jjj>n>>m)
	{
		 1.输入线性方程组,最后一列存结果///
		if(nm)cout<<"方程组个数大于未知数个数,但有些项可以消去,有无穷多组解!"<m)cout<<"方程组个数大于未知数个数,但有些项可以消去,有唯一一组解!"<
//LU分解法
#include
#include
#include
#include
using namespace std;
//定理 若A是非奇异矩阵,则A能分解为LU的充分必要条件是A的顺序主子式均不为0
//n 阶方阵 A 是非奇异方阵的充要条件是 A 为可逆矩阵,也即A的行列式不为零。


int n,m;
char varible[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
double *y,*root;

double iteration_y(double **linear,int i)
//中间过程下三角矩阵递推求LY=b中y[i]
{
	if(i==1)
		return linear[i][m+1];
	else 
	{
		double sum=linear[i][m+1]  ;
		for(int j=1;jfabs(linear[max_index][k]))
				max_index=j;
		}
		if(max_index!=k)
		{
			cout<<"该线性方程组对应的矩阵的第"<>n>>m)
	{
		判断是否为方阵,进行LU分解的前提//
		if(n!=m)
		{
			cout<<"你的线性方程组对应的矩阵行列不相等,属非奇异的矩阵,无法用LU分解法求解!"<=n)
				{
					cout<j)cout<


你可能感兴趣的:(数值计算)