1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 高斯列主元消元法求解线性方程组

高斯列主元消元法求解线性方程组

时间:2023-09-02 18:38:57

相关推荐

高斯列主元消元法求解线性方程组

一、高斯消去法的基本思想

例1. 解方程组:

解 方程组矩阵形式为:AX=b,其中:

第一步,消元过程:对增广矩阵进行消元

第二步, 回代过程:

此方法就是高斯消去法

二、改进版算法

由高斯消去法知道,在消元过程中可能出现=0的情况, 这时消去法将无法进行;即使主元素≠0,但很小时,用其作除数,会导致其他元素数量级的严重增长和舍入误差的扩散, 最后也使得计算解不可靠。

引例 求解方程组

4位浮点数进行计算。

解: 方法1用高斯消去法求解。

其中

计算解为:

显然计算解是一个很坏的结果,不能作为方程的近似解。

方法2交换行,避免绝对值小的主元做除数。

得计算解为:

x=(-0.4900,-0.05113,0.3678)T≈x*.

这个例子告诉我们,在采用高斯消去法解方程组时,小主元可能产生麻烦,故应避免采用绝对值小的主元素a 。对一般矩阵来说,最好每一步选取系数矩阵(或消元后的低价矩阵)中绝对值最大的元素作为主元素,以使高斯消去法具有较好的数值稳定性, 这就是全主元素消去法, 在选主元时要花费较多机器时间,目前主要使用的是列主元消去法

本节主要介绍列主元消去法,并假定(2.1)的 A∈Rn×n 为非奇异的。

1 . 列主元素消去法

设方程组(2.1)的增广矩阵为:

首先在A的第一列中选取绝对值最大的元素作为主元素,例如:

|ai1,1|= max |ai1|≠0, 1≤i≤n

然后交换B的第一行与第i1行,经第一次消元计算得

(A|b)→(A(2)|b(2))

重复上述过程,设已完成第k-1步的选主元素,交换两行及消元计算,(A|b)约化为:

(2.2)

其中A(k)的元素仍记为aij,b(k)的元素仍记为bi

k步选主元素(A(k)右下角方阵的第一列内选),即确定ik,使

交换(A(k)|b(k))k行与ik列的元素,再进行消元计算,最后将原方 程组化为(k=1,2…,n-1):

回代求解

2. 高斯-若当消去法

高斯消去法始终是消去对角线下方的元素,现考察高斯消去法的一种修正,即消去对角线下方和上方的元素,这种方法称为高斯-若当( Gauss—Jordan )消去法。通过选主元,消元等过程最终化为:

说明:用高斯-若当方法将A约化为单位矩阵,计算解就在常数位置得到,因此用不着回代求解,用高斯-若当方法解方程组其计算量要比高斯消去法大,但用高斯—若当方法求一个矩阵的逆矩阵还是比较合适的。

定理4(高斯-若当法求逆矩阵)设 A 为非奇异矩阵,C=(A|In), 如果对C应用高斯—若当方法化为(In|T)

A-1=T 。

4用高斯-若当方法求 的逆矩阵以及 的解。

解:

c++代码实现如下:

/** test.cpp** Created on: -1-5*Author: zhijian*/#include <stdio.h>#include <math.h>#define MAXN 100#define ZERO 0.000000001//定义浮点0//#define DEBUG//交换两个变量的值void swap(double *a,double *b){double temp = *a;*a = *b;*b = temp;}//B行的每一个元素加上A行的每一个元素的值*kvoid lineOper(double A[],double B[],int n,double k){for(int i = 0;i<n;i++)B[i] += A[i] * k;}/** 解线性方程组Ax = b,* 其中A为n*n的方阵,x,b为n维向量* 返回是否有解*/bool solveEquations(double A[MAXN][MAXN],int n,double x[MAXN],double b[MAXN]){double temp[MAXN][MAXN + 1];//增广矩阵//初始化增广矩阵for(int i = 0;i<n;i++){for(int j = 0;j<n;j++)temp[i][j] = A[i][j];temp[i][n] = b[i];}//化为上三角矩阵for(int j = 0;j<n;j++){//寻找该列绝对值最大的行int mmaxi = j;for(int i = j+1;i<n;i++)if(fabs(temp[i][j])>fabs(temp[mmaxi][j]))mmaxi = i;if(fabs(temp[mmaxi][j])<ZERO)return false;//无解if(mmaxi != j){//交换两行for(int i = 0;i<n+1;i++)swap(&temp[mmaxi][i],&temp[j][i]);}//消元for(int i = j + 1;i<n;i++){double k = temp[i][j] / temp[j][j];lineOper(temp[j],temp[i],n+1,-k);}}//迭代求值for(int j = n - 1;j>=0;j--){double sum = 0;for(int i = j+1;i<n;i++)sum += x[i] * temp[j][i];x[j] = (temp[j][n] - sum) / temp[j][j];}return true;}void test(){double A[MAXN][MAXN];double x[MAXN];double b[MAXN];int n;printf("请输入矩阵A的规模:\n");scanf("%d",&n);printf("请按行输入矩阵A:\n");for(int i = 0;i<n;i++)for(int j = 0;j<n;j++)scanf("%lf",&A[i][j]);printf("请输入向量b:\n");for(int i = 0;i<n;i++)scanf("%lf",&b[i]);if(!solveEquations(A,n,x,b))printf("无解\n");else{for(int i = 0;i<n;i++)printf("%lf\n",x[i]);}}int main(){test();return 0;}

求逆的实现:

/** test.cpp** Created on: -1-5*Author: zhijian*/#include <stdio.h>#include <math.h>#define MAXN 100#define ZERO 0.000000001//定义浮点0#define DEBUG//交换两个变量void swap(double *a,double *b){double temp = *a;*a = *b;*b = temp;}//交换两行变量void swapLine(double A[],double B[],int n){for(int i = 0;i<n;i++)swap(&A[i],&B[i]);}//将一行(B)的每一个元素加上另外一行(A)的每一个元素*kvoid lineOper(double A[],double B[],int n,double k){for(int i = 0;i<n;i++)B[i] += k * A[i];}/**** 矩阵求逆* 返回是否有逆*/bool inverse(double A[MAXN][MAXN],int n,double A_[MAXN][MAXN]){double temp[MAXN][MAXN];//辅助矩阵//单位矩阵初始化for(int i = 0;i<n;i++){for(int j = 0;j<n;j++)A_[i][j] = 0,temp[i][j] = A[i][j];A_[i][i] = 1;}//化成上三角矩阵for(int j = 0;j<n;j++){int mmaxi = j;for(int i = j + 1;i<n;i++)if(fabs(temp[i][j])>fabs(temp[mmaxi][j]))mmaxi = i;if(fabs(temp[mmaxi][j])<ZERO)return false;//无逆if(mmaxi != j){swapLine(temp[mmaxi],temp[j],n);swapLine(A_[mmaxi],A_[j],n);}for(int i = j+1;i<n;i++){double k = temp[i][j] / temp[j][j];lineOper(temp[j],temp[i],n,-k);lineOper(A_[j],A_[i],n,-k);}}//变成对角矩阵for(int j = n-1;j>=0;j--){for(int i = 0;i<j;i++){double k = temp[i][j] / temp[j][j];lineOper(temp[j],temp[i],n,-k);lineOper(A_[j],A_[i],n,-k);}}//单位化for(int i = 0;i<n;i++){double k = 1.0 / temp[i][i];for(int j = 0;j<n;j++)A_[i][j] *= k;}return true;}void test(){double A[MAXN][MAXN];double A_[MAXN][MAXN];int n;printf("输入方阵规模\n");scanf("%d",&n);for(int i = 0;i<n;i++)for(int j = 0;j<n;j++)scanf("%lf",&A[i][j]);if(!inverse(A,n,A_)){printf("无解\n");}else{for(int i = 0;i<n;i++){for(int j = 0;j<n;j++)printf("%lf ",A_[i][j]);printf("\n");}printf("\n");}}int main(){test();return 0;}

参考链接:http://sxyd./zhanshi/shuzhifenxi/shuzhifenxi/2.1/szfx021.htm

http://sxyd./zhanshi/shuzhifenxi/shuzhifenxi/2.2/szfx022.htm

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。