高斯消去法求解线性方程组解

作者在 2012-02-16 21:32:07 发布以下内容

    数学上,高斯消元法(或译:高斯消去法),是线性代数中的一个算法,可用来为线性方程组求解,求出矩阵的秩,以及求出可逆方阵的逆矩阵。当用于一个矩阵时,高斯消元法会产生出一个“行梯阵式”。高斯消元法可以用在电脑中来解决数千条等式及未知数。不过,如果有过百万条等式时,这个算法会十分费时。一些极大的方程组通常会用迭代法来解决。亦有一些方法特地用来解决一些有特别排列的系数的方程组。

 高斯消元法可用来找出下列方程组的解或其解的限制:

2x + y - z = 8 (L1)
-3x - y + 2z = -11 (L2)
-2x + y + 2z = -3 (L3)
这个算法的原理是:
首先,要将L1 以下的等式中的x 消除,然后再将L2 以下的等式中的y 消除。这样可使整个方程组变成一个三角形似的格式。之后再将已得出的答案一个个地代入已被简化的等式中的未知数中,就可求出其余的答案了。
在刚才的例子中,我们将3/2 L1和L2相加,就可以将L2 中的x 消除了。然后再将L1 和L3相加,就可以将L3 中的x 消除。
我们可以这样写:
L2 + 3/2 L1→ L2
L3 + L1 → L3
结果就是:
2x + y - z = 8
1/2 y + 1/2 z = 1
2y + z = 5
现在将 − 4L2 和L3 相加,就可将L3 中的y 消除:
L3 + -4 L2 → L3
其结果是:
2x + y - z = 8
1/2y + 1/2z = 1
-z = 1
这样就完成了整个算法的初步,一个三角形的格式(指:变量的格式而言,上例中的变量各为3,2,1个)出现了。
第二步,就是由尾至头地将已知的答案代入其他等式中的未知数。第一个答案就是:
z = -1
然后就可以将z 代入L2 中,立即就可得出第二个答案:
y = 3
之后,将z 和y 代入L1 之中,最后一个答案就出来了:
x = 2
就是这样,这个方程组就被高斯消元法解决了。
这种算法可以用来解决所有线性方程组。即使一个方程组不能被化为一个三角形的格式,高斯消元法仍可找出它的解。例如在第一步化简后,L2 及L3 中没有出现任何y ,没有三角形的格式,照着高斯消元法而产生的格式仍是一个行梯阵式。这情况之下,这个方程组会有超过一个解,当中会有至少一个变量作为答案。每当变量被锁定,就会出现一个解。
通常人或电脑在应用高斯消元法的时候,不会直接写出方程组的等式来消去未知数,反而会使用矩阵来计算。以下就是使用矩阵来计算的例子:
2 1 -1 8
-3 -1 2 -11
-2 1 2 -3
跟着以上的方法来运算,这个矩阵可以转变为以下的样子:
2 1 -1 8
0 1/2 1/2 1
0 0 -1 1
矩阵叫做“行梯阵式”。
最后,可以利用同样的算法产生以下的矩阵,便可把所得出的解或其限制简明地表示出来:
1 0 0 2
0 1 0 3
0 0 1 -1
最后这矩阵叫做“简化行梯阵式”,亦是高斯-约当消元法指定的步骤。(以上分析引自百度百科)


#include <iostream>
#include <stdio.h>
#include <math.h>
#include <iomanip>
using namespace std;

#define N 3

static double a[N][N]= {{2,6,3},{4,7,7},{-2,4,5}};
static double aa[N][N]= {{2,6,3},{4,7,7},{-2,4,5}};
static double b[N]= {3,1,-7};
static double bb[N]= {3,1,-7};
void print()
{
    for(int i=0; i<N; i++)
    {
        for(int j=0; j<N; j++)
        {
            cout<<setw(15)<<left<<a[i][j];
        }
        cout<<b[i]<<endl;
    }
}
bool check(double *x)
{
    int flag=1;
    for(int i=0;i<N;i++)
    {
        double temp=0;
        for(int j=0;j<N;j++)
        {
            temp=temp+aa[i][j]*x[j];
        }
        if(temp!=bb[i])
        {
            cout<<"方程组解有误!第"<<i+1<<"方程验证不通过"<<endl;
            cout<<"左边="<<showpoint<<temp<<"   右边="<<showpoint<<bb[i]<<endl;
            flag=0;
            //break;
        }
    }
    return flag;
}

int main()
{
    double x[N]= {0};
    cout<<"高斯消去法仅仅可以对系数矩阵为满秩矩阵的方程组求解"<<endl;
    print();
    for(int i=0; i<N-1; i++) ///////////////对每一列找主元消去(最后一列除外)
    {
        double temp=a[i][i];
        int p;
        for(int j=i; j<N; j++) /////////找主元
        {
            if(fabs(a[j][i])>temp)
            {
                temp=fabs(a[j][i]);
                //cout<<temp<<endl;
                p=j;
            }
        }
        //////////////////////////////交换行
        for(int j=i; j<N; j++)
        {
            double tem;
            tem=a[i][j];
            a[i][j]=a[p][j];
            a[p][j]=tem;
        }

        {
            double tem;
            tem=b[p];
            b[p]=b[i];
            b[i]=tem;
        }
        cout<<"找第"<<i+1<<"个主元后:"<<endl;
        print();
        /////////////////////////////////////////////
        if(a[i][i]==0)
        {
            cout<<"初等变换后系数矩阵第"<<i<<"列全为0,方程组有无数个解"<<endl;
            break;
        }
        else
        {
            for(int p=i+1; p<N; p++)
            {
                double rand;
                rand=a[p][i]/a[i][i];
                if(rand!=0)
                {
                    cout<<"对第"<<i+1<<"个主元对第"<<p+1<<"行消去(消去系数="<<rand<<"):"<<endl;
                    for(int q=i; q<N; q++)
                    {
                        //cout<<"前a["<<p+1<<"]["<<q+1<<"]="<<a[p][q]<<endl;
                        
//cout<<"a[i][q]*rand="<<a[i][q]*rand<<endl;
                        a[p][q]=a[p][q]-a[i][q]*rand;
                        //cout<<"后a["<<p+1<<"]["<<q+1<<"]="<<a[p][q]<<endl;
                    }
                    b[p]=b[p]-b[i]*rand;
                    print();
                }
            }
        }
    }
    for(int i=N-1;i>=0;i--)
    {
        double temp=0;
        for(int j=i;j<N;j++)
        {
            if(j>i)
            temp=temp+a[i][j]*x[j];
        }
        x[i]=(b[i]-temp)/a[i][i];

    }
    cout<<"/////////////////////////////////////////////////"<<endl;
    for(int i=0;i<N;i++)
    {
        cout<<"x"<<i+1<<"="<<x[i]<<setw(10)<<right;
    }cout<<endl;
    if(check(x))cout<<"验证成功"<<endl;
    //cout << "Hello world!" << endl;
    return 0;
}

文章评论,共0条
游客请输入验证码
浏览70038次