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

C 語言生成任意大小隨機可逆方陣:演算法與實作

     編輯:關於C

背景動機

平行運算作業需對大型矩陣求逆,驗證平行優勢需大規模資料集。隨機產生的矩陣多半不可逆(行列式為 0),導致求逆失敗。本文實作「單位矩陣 + 有限次初等列變換」策略,保證產生可逆矩陣,並解決溢位與分布均勻問題。

核心演算法思路

  1. 建立 n×n 單位矩陣(對角線 1,其餘 0)。
  2. 重複隨機次數(< 1000)的初等列變換:
    隨機選一主列 → 隨機產生乘數 → 將主列乘乘數加到其他列。
    關鍵:每次加法前檢測 int16_t 範圍(-32768~32767)是否溢位,若溢位則改用除法縮小數值(/4)保持穩定。
  3. 變換結束後,矩陣必可逆(初等列變換不改變行列式是否為零)。
  4. 依指定格式寫入檔案(每列以 Tab 分隔,末尾無分隔)。

完整程式碼實作

主程式與記憶體管理

#include 
#include 
#include 
#include   // UINT16_MAX

void getIdentityMatrix(int n, int **a);
void getInvertibleMatrix(int n, int **a);
int putInvertibleMatrixIntoFile(int n, int **a);
void printInvertibleMatrix(int n, int **a);
void freeMatrix(int n, int **a);

int main() {
    int n, flag;
    printf("請輸入方陣階數: ");
    scanf("%d", &n);
    int **matrix = malloc(n * sizeof(int *));
    for (int i = 0; i < n; ++i) matrix[i] = malloc(n * sizeof(int));

    printf("輸入 0 產生單位矩陣,1 產生可逆矩陣: ");
    scanf("%d", &flag);
    getIdentityMatrix(n, matrix);
    if (flag == 1) getInvertibleMatrix(n, matrix);
    putInvertibleMatrixIntoFile(n, matrix);
    printInvertibleMatrix(n, matrix);
    freeMatrix(n, matrix);
    return 0;
}

void freeMatrix(int n, int **a) {
    for (int i = 0; i < n; ++i) free(a[i]);
    free(a);
}

單位矩陣生成

void getIdentityMatrix(int n, int **a) {
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            a[i][j] = (i == j) ? 1 : 0;
}

可逆矩陣生成(核心邏輯)

void getInvertibleMatrix(int n, int **a) {
    srand((unsigned)time(NULL));
    int times = rand() % 1000;
    printf("將執行 %d 次列變換\n", times);

    int *temp = malloc(n * sizeof(int));
    for (int t = 0; t < times; ++t) {
        int mainRow = rand() % n;
        // 產生處理後的主列暫存
        for (int k = 0; k < n; ++k) {
            int factor = rand() % 5 - 10; // -10 ~ -6
            long val = (long)a[mainRow][k] * factor;
            // 溢位檢測 (int16_t 範圍)
            if (val > INT16_MAX || val < -INT16_MAX - 1)
                temp[k] = a[mainRow][k];
            else
                temp[k] = (int)val;
        }
        // 加到其他列
        for (int j = 0; j < n; ++j) if (j != mainRow) {
            for (int k = 0; k < n; ++k) {
                long sum = (long)a[j][k] + temp[k];
                if (sum > INT16_MAX || sum < -INT16_MAX - 1)
                    a[j][k] /= 4;  // 縮小避免溢位
                else
                    a[j][k] = (int)sum;
            }
        }
    }
    free(temp);
}

寫入檔案

int putInvertibleMatrixIntoFile(int n, int **a) {
    FILE *fp = fopen("input", "w");
    if (!fp) return -1;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            fprintf(fp, "%d%s", a[i][j], (j == n-1) ? "" : "\t");
        }
        fputs("\n", fp);
    }
    fclose(fp);
    return 1;
}

編譯與測試

gcc -o invertible invertiblematrix.c
./invertible
# 輸入 5 並選 1,輸出 5x5 可逆矩陣至 input 檔

實測 5×5 矩陣執行 780 次變換,產生的矩陣經驗證可成功求逆。大規模矩陣(如 500×500)同樣適用,滿足平行運算資料需求。

改進方向

  • 採用 double 型別並配合部分樞軸高斯消去法,進一步提升數值穩定性。
  • 引入隨機排列矩陣(Permutation Matrix)增加結構多樣性。
  • 輸出標準 Matrix Market 格式(.mtx),便於科學計算庫讀取。

此專案展示如何以純 C 語言解決「隨機且可逆」矩陣生成問題,為後續高效能運算奠基。

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