計算方法實驗(五):高斯列主元消去法

Gauss列主元消去法數學原理

高斯(Gauss)列主元消去法:對給定的nn階線性方程組Ax=bAx = b,首先進行列主元消元過程,然後進行回代過程,最後得到解或確定該線性方程組是奇異的。

如果係數矩陣的元素按絕對值在數量級方面相差很大,那麼,在進行列主元消元過程前,先把係數矩陣的元素進行行平衡:係數矩陣的每行元素和相應的右端向量元素同除以該行元素絕對值最大的元素。這就是所謂的平衡技術。然後再進行列主元消元過程。

如果真正進行運算去確定相對主元,則稱爲顯式相對Gauss列主元消去法;如果不進行運算,也能確定相對主元,則稱爲隱式相對Gauss列主元消去法。

顯式相對Gauss列主元消去法:對給定的nn階線性方程組Ax=bAx = b,首先進行列主元消元過程,在消元過程中利用顯式平衡技術,然後進行回代過程,最後得到解或確定該線性方程組是奇異的。

隱式相對Gauss列主元消去法:對給定的nn階線性方程組Ax=bAx = b,首先進行列主元消元過程,在消元過程中利用隱式平衡技術,然後進行回代過程,最後得到解或確定該線性方程組是奇異的。

Gauss列主元消去法

1對k=1,2,,n1k = 1,2,\cdots,n - 1,做1.1—1.3,消元過程

1.1 尋找最小的正整數ppkpnk \leq p \leq napk=maxkjnajk\left| a_{\text{pk}} \right| = \max_{k \leq j \leq n}\left| a_{\text{jk}} \right|。如果apk=0a_{\text{pk}} = 0,輸出奇異標誌,停機;

1.2 如果pkp \neq k,那麼交換p,kp,k兩行;

1.3 對i=k+1,,ni = k + 1,\cdots,n,記mik=aik/akkm_{\text{ik}} = a_{\text{ik}}/a_{\text{kk}}$,計算

{ aij=aijakjmik i=k+1,,n j=k+1,,n bi=bibkmik i=k+1,,n  \left\{ \begin{matrix} \ a_{\text{ij}} = a_{\text{ij}} - a_{\text{kj}}m_{\text{ik}} \\ \ i = k + 1,\cdots,n \\ \ j = k + 1,\cdots,n \\ \ b_{i} = b_{i} - b_{k}m_{\text{ik}} \\ \ i = k + 1,\cdots,n \\ \end{matrix} \right.\

  1. 如果ann=0a_{\text{nn}} = 0輸出奇異標誌,停機;

  2. xn=bn/annx_{n} = b_{n}/a_{\text{nn}},回代過程

  3. k=n1,,2,1k = n - 1,\cdots,2,1,置 xk=(bkj=k+1nakjxj)/akkx_{k} = (b_{k} - \sum_{j = k + 1}^{n}{a_{\text{kj}}x_{j}})/a_{\text{kk}}

程序流程

代碼

#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define N 10

int n;
double a[N][N], b[N], x[N];

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) scanf("%lf", &a[i][j]);
    for (int i = 1; i <= n; i++) scanf("%lf", &b[i]);
    for (int k = 1; k < n; k++) {
        int p = k;
        double maxabs = fabs(a[k][k]);
        for (int j = k + 1; j <= n; j++)
            if (fabs(a[j][k]) - maxabs > 0) {
                p = j;
                maxabs = fabs(a[j][k]);
            }
        if (a[p][k] == 0) {
            printf("Singular");
            return 0;
        }
        if (p != k) {
            double tmp;
            for (int j = 1; j <= n; j++) {
                tmp = a[p][j];
                a[p][j] = a[k][j];
                a[k][j] = tmp;
            }
            tmp = b[p];
            b[p] = b[k];
            b[k] = tmp;
        }
        for (int i = k + 1; i <= n; i++) {
            double m_ik = a[i][k] / a[k][k];
            for (int j = k + 1; j <= n; j++) a[i][j] -= a[k][j] * m_ik;
            b[i] -= b[k] * m_ik;
        }
    }
    if (a[n][n] == 0) {
        printf("Singular");
        return 0;
    }
    x[n] = b[n] / a[n][n];
    for (int k = n - 1; k >= 1; k--) {
        double sigma = 0.0;
        for (int j = k + 1; j <= n; j++) sigma += a[k][j] * x[j];
        x[k] = (b[k] - sigma) / a[k][k];
    }
    for (int i = 1; i <= n; i++) printf("%lf\t", x[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章