首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

從零手寫高斯消去法:線性方程組求解的 C 語言實現全過程

     編輯:關於C語言

問題引入

給定 n 元線性方程組:

A x = b

其中 A 為 n×n 係數矩陣,b 為常數向量。高斯消去法通過初等行變換將增廣矩陣 [A|b] 化為上三角矩陣,再回代求解。

算法步驟拆解

  1. 前向消去:對第 k 列 (0 ≤ k < n-1),以 A[k][k] 為主元,將第 k+1 至 n-1 行的第 k 列消為 0。
  2. 主元選擇 (可選):若 A[k][k] ≈ 0,尋找下方非零行交換 (列主元/全主元),提高數值穩定性。
  3. 回代求解:從最後一行向上,逐個求出 x[n-1] … x[0]。

完整 C 實現 (含註釋與防禦)


#include 
#include    // fabs
#include  // exit

#define MAX_N 100   // 最大未知數個數

/* 打印增廣矩陣,用於調試觀察中間過程 */
void printMatrix(int n, double a[][MAX_N+1], const char* tag)
{
    printf("\n=== %s ===\n", tag);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j <= n; j++)
            printf("%10.4f ", a[i][j]);
        printf("\n");
    }
}

/* 高斯消去法主函數
 * 參數:
 *   n  - 方程個數/未知數個數
 *   a  - 增廣矩陣 [n][n+1],最後一列為常數項 b
 *   x  - 輸出解向量 (長度 n)
 * 返回: 0 成功, -1 奇異矩陣/無唯一解
 */
int gaussianElimination(int n, double a[][MAX_N+1], double x[])
{
    const double EPS = 1e-12; // 判零閾值

    /* --- 前向消去 --- */
    for (int k = 0; k < n - 1; k++) {
        /* 列主元選擇:尋找第 k 列下方絕對值最大的行 */
        int maxRow = k;
        for (int i = k + 1; i < n; i++)
            if (fabs(a[i][k]) > fabs(a[maxRow][k]))
                maxRow = i;

        if (fabs(a[maxRow][k]) < EPS) {
            fprintf(stderr, "第 %d 列主元接近零,矩陣奇異或無唯一解\n", k);
            return -1;
        }

        if (maxRow != k) {
            // 行交換
            for (int j = k; j <= n; j++) {
                double tmp = a[k][j];
                a[k][j] = a[maxRow][j];
                a[maxRow][j] = tmp;
            }
            printMatrix(n, a, "行交換後");
        }

        // 消去第 k 列下方元素
        for (int i = k + 1; i < n; i++) {
            double factor = a[i][k] / a[k][k];
            for (int j = k; j <= n; j++) // 從 k 開始可減少運算
                a[i][j] -= factor * a[k][j];
        }
        printMatrix(n, a, "消去後");
    }

    /* 檢查最後一行主元 */
    if (fabs(a[n-1][n-1]) < EPS) {
        fprintf(stderr, "最後一行主元為零,無唯一解\n");
        return -1;
    }

    /* --- 回代求解 --- */
    for (int i = n - 1; i >= 0; i--) {
        double sum = a[i][n]; // 常數項
        for (int j = i + 1; j < n; j++)
            sum -= a[i][j] * x[j];
        x[i] = sum / a[i][i];
    }
    return 0;
}

/* === 測試主程序 === */
int main()
{
    // 測試方程組:
    //  x + y     - 4z =  1
    // -x + y + z + 3w = -2
    //  x + 3y + 5z - 4w = -4
    //     y + 2z -  w = -2
    // 解: x=1, y=-1, z=0, w=1
    int n = 4;
    double a[MAX_N][MAX_N+1] = {
        { 1,  1,  0, -4,  1},
        {-1,  1,  1,  3, -2},
        { 1,  3,  5, -4, -4},
        { 0,  1,  2, -1, -2}
    };
    double x[MAX_N] = {0};

    printMatrix(n, a, "初始增廣矩陣");

    if (gaussianElimination(n, a, x) == 0) {
        printf("\n=== 解向量 ===\n");
        for (int i = 0; i < n; i++)
            printf("x[%d] = %10.6f\n", i, x[i]);
    } else {
        printf("求解失敗\n");
    }
    return 0;
}

關鍵工程細節

1. 列主元選擇

消除 factor = a[i][k] / a[k][k] 中分母過小導致的數值放大誤差。生產級代碼必須包含。

2. 就地修改增廣矩陣

空間復雜度 O(1) 額外空間。若需保留原矩陣,調用前 memcpy 備份。

3. 浮點數比較用 EPS

絕不直接 == 0,使用 fabs(val) < 1e-12 (視問題尺度調整)。

4. 迴圈邊界優化

消去內層迴圈 j = k; j <= n; j++,因 j < k 列已為 0,無需運算。

5. 調試可視化

printMatrix 讓中間過程可見,教學與除錯利器。

進階擴展方向

方向描述
全主元掃描在剩餘子矩陣中找絕對值最大元素作主元,雙重交換行列,穩定性最強
LU 分解將 A 分解為 L·U,同一係數矩陣多個右端向量求解時極快
稀疏矩陣優化採用壓縮存儲 (CSR/CSC) + 迭代法 (CG/GMRES),大規模問題必備
任意精度引入 GMP/MPFR 庫,解決極端病態矩陣
並行化OpenMP 並行化消去迴圈,GPU 加速 (cuSOLVER/MAGMA)

驗證輸出


=== 初始增廣矩陣 ===
     1.0000      1.0000      0.0000     -4.0000      1.0000
    -1.0000      1.0000      1.0000      3.0000     -2.0000
     1.0000      3.0000      5.0000     -4.0000     -4.0000
     0.0000      1.0000      2.0000     -1.0000     -2.0000

=== 解向量 ===
x[0] =   1.000000
x[1] =  -1.000000
x[2] =   0.000000
x[3] =   1.000000

✅ 與手算結果完全一致。

總結

高斯消去法是線性代數數值計算的基石。本文從數學原理 → 算法流程 → 防禦性 C 實現 → 調試可視化 → 擴展方向完整呈現。關鍵收穫:

  1. **列主元選擇是生產代碼的標配**,不是可選優化。
  2. **增廣矩陣就地操作** 節省內存,適合嵌入式/教學環境。
  3. **可視化中間矩陣** 能直觀理解消去過程,排除邏輯錯誤。
  4. 理解其 O(n³) 複雜度與數值穩定性局限,知道何時升級到 LU/迭代法/稀疏求解器。

這份代碼可直接作為教學演示、嵌入式小規模求解、或大型求解器原型的參考實現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved