• 高斯消元


    求n元一次方程组的解,我们知道n元一次方程组需要n个式子我们可以把n个式子写成n*(n+1)的矩阵,最后一列是等号右边的常数。

    回忆一下我们小学学的二元一次方程组,其中一个式子所有系数乘以k,等式仍然成立,到我们的矩阵里就是某一行所有数同时乘或除一个数式子仍然成立;还有加减消元,就是令第一行-第二行,使得某一个未知数的系数变为0,变成kx=b的形式从而求的x的值,在矩阵里就是我们可以让某一行的式子减去另一行的k倍,从而消去一个变量的系数。来看一下我们的高斯消元是怎么做的:

      step1:把第i行的第i个数变成1,也就是我们打算用第i行来求第i个元素的值,想让第i个系数变成1只需要让第i行左右两边同时除以第i个系数就可以了。

      step2:把除了第i行之外的其他行的第i个系数都变成0,这个稍微复杂一点点,我们慢慢来讲

    首先最后达到的效果是

    1 0 0   x

    0 1 0  y

    0 0 1  z

    其中x,y,z都是常数,那么显然a1=x,a2=y,a3=z,接下来我们只需要考虑如何来实现step2,假设我们现在正在处理第i个元素,并且已经完成了第一步,这时除了对角线,每一行的前i-1个系数都是0了,并且a[i][i]=1,a[j][i](即第j行的第i个元素)就是a[i][i]的a[j][i]倍,那么第j行减a[j][i]倍的第i行就可以使第j行的第i个元素系数变为0了,并且由于第i行的前i-1个数都是0,不会对已经求出来的0造成任何影响。

    最后还有一点值得注意的就是,如果有一个未知数他的所有系数都是0,那么这个未知数是无法确定的,所以方程无解

    代码:

    #include<iostream>
    #include<cstdio>
    #define eps 1e-8
    using namespace std;
    int n;
    double a[110][110];
    template<typename T>T ab(T &a)
    {
        return a>0?a:-a;
    }
    //把第i行第i列的元素系数变成1,第i行其他元素系数变成0,那么第i行就存储着第i个元素的值 
    bool gauss()
    {
        for(int i=1;i<=n;++i)//循环每一个元素
        {
            int k=i;
            for(int j=i+1;j<=n;++j)
                if(ab(a[j][i])>ab(a[k][i]))k=j;//找这个元素的最大的系数 
            if(ab(a[k][i])<eps)
            {
                return 1;//相当于是0,系数都是0代表无解 
            }
            swap(a[i],a[k]);//运算系数最大的那一行,减小误差 
            double now=a[i][i];
            for(int j=1;j<=n+1;++j)a[i][j]/=now;//首先这一行的每个数都除以a[i][i]就可以使a[i][i]变成1 
            a[i][i]=1;
            for(int j=1;j<=n;++j)//把第i列的其他元素都变成0 ,所以得循环每一行 
            {
                if(j!=i) 
                {
                    double now=a[j][i];
                    for(int k=1;k<=n+1;++k)
                        a[j][k]-=now*a[i][k];//加减消元把其他的都消掉 
                    //第j行减去now倍的第j行 ,因为第i行系数是1,第j行系数是a[j][i],所以得都减去now倍的才能变成0 
                    //这一行都减去其他行的now倍,矩阵值不变 
                }
            }
        }
        return 0;
    }
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n+1;++j)
                scanf("%lf",&a[i][j]);
        if(gauss())printf("No Solution");
        else{
            for(int i=1;i<=n;++i)printf("%.2lf
    ",a[i][n+1]);
        }
        return 0;
    }
  • 相关阅读:
    成功在RedFlag Linux 5.0桌面版安装oralce10
    ORACLE ebs 11.5.10 for linux 安装心得
    C#讀取轉換Excel檔案的優化(源代碼)
    [轉]SAP BASIS经验十年James Yen
    SAP Basis 常用事务代码
    健康指南:人体十大最佳黄金时间
    中國人使筷子的十二種忌諱
    SAP basis 相关设定
    技术出身,如何做好项目经理?
    [轉貼]奋斗5年从月薪3500到700万!
  • 原文地址:https://www.cnblogs.com/yuelian/p/12493138.html
Copyright © 2020-2023  润新知