C语言实现 求解逆矩阵

C语言实现 求解逆矩阵

近期刚刚完成对考研概率论基础的复盘,于是乎开始回忆起之前温习后不久的线代,对于矩阵的理论部分,只觉除纸笔来回间的套路手算以外还未有过代码层面的解读经历,鉴于此,便开始仔细回观线代,辅以先者的思路,目前为止,为从更底层的逻辑中掌握含义,就选择使用了C语言来实现功能,以下就是一个能够跑通的实现模块。个人所为,难免疏漏,仅作参考。

算法思路

  1. 将相同行列的单位矩阵拼接在原矩阵的右侧以对原矩阵进行扩展,获得行数不变、列数倍增的扩展矩阵;
  2. 对扩展后的矩阵进行初等行变换,得到左半部分为单位矩阵的新矩阵;
  3. 截取新矩阵的右半部分,即为所求的逆矩阵
  • 需要注意的是,在对原矩阵扩展之前,需要判定其是否符合扩展条件,即原矩阵是否存在逆矩阵。

实现代码

#include 
#include 

#define true 1
#define false 0

double** expand_matrix;
double** new_matrix;

void initExpandMatrix(double ** mat, double ** expand_mat, int);
int adjustMatrix(double ** expand_mat, int len);
void calculateExpandMatrix(double ** expand_mat, int len);
void getNewMatrix(double ** expand_mat, double ** new_mat, int len);
void printMatrix(double ** mat, int len);
double** getProductMatrix(double ** init_mat, double ** new_mat, int len);
double** getInvMatrix(double ** mat, int len);

int main() {
    int len;
    scanf("%d", &len);
    double** init_mat = (double **)malloc(sizeof(double *) * len);
    for (int i = 0; i < len; i++) {
        init_mat[i] = (double *)malloc(sizeof(double) * len);
    }
     /* 测试示例
		1 2 -1
		3 4 -2
		5 -4 1
     */
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < len; j++) {
            scanf("%lf", &init_mat[i][j]);
        }
    }
    printf("====== init_matrix ======\n");
    printMatrix(init_mat, len);

    printf("==== inverse matrix ====\n\n");
    double ** new_mat = getInvMatrix(init_mat, len);
    printMatrix(new_mat, len);

    printf("====== init * inv ======\n\n");
    double** product_mat = getProductMatrix(init_mat, new_mat, len);
    printMatrix(product_mat, len);
    return 0;
}

// inverse matrix
double** getInvMatrix(double ** mat, int len) {
    // 扩展矩阵定义 //
    expand_matrix = (double**)malloc(sizeof(double *) * len);
    for (int i = 0; i < len; i++) {
        expand_matrix[i] = (double *)malloc(sizeof(double ) * (len * 2));
    }

    // 逆矩阵定义 //
    new_matrix = (double**)malloc(sizeof(double *) * len);
    for (int i = 0; i < len; i++) {
        new_matrix[i] = (double *)malloc(sizeof(double ) * len);
    }

    // init
    initExpandMatrix(mat, expand_matrix, len);

    // adjust
    int canAdjust = adjustMatrix(expand_matrix, len);

    if (canAdjust == 0) {
        return NULL;
    }

    // calc expand
    calculateExpandMatrix(expand_matrix, len);

    // 取后面的N*N矩阵,即为所求 //
    getNewMatrix(expand_matrix, new_matrix, len);

    return new_matrix;
}


// init expand_matrix
void initExpandMatrix(double ** mat, double ** expand_mat, int len) {
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < len * 2; j++) {
            if (j < len) {
                expand_mat[i][j] = mat[i][j];
            } else {
                if (j == len + i) {
                    expand_mat[i][j] = 1;
                } else {
                    expand_mat[i][j] = 0;
                }
            }
        }
    }
}


// adjust expand matrix
int adjustMatrix(double ** expand_mat, int len) {

    for (int i = 0; i < len; i++) {
        if (expand_mat[i][i] == 0) {
            int j;
            for (j = 0; j < len; j++) {
                if (expand_mat[j][i] != 0) {
                    double* tmp = expand_mat[i];
                    expand_mat[i] = expand_mat[j];
                    expand_mat[j] = tmp;
                    break;
                }
            }
            if (j >= len) {
                printf("Inv Matrix does not exists\n");
                return false;
            }
        }
    }
    return true;
}


// calc
void calculateExpandMatrix(double ** expand_mat, int len) {
    for (int i = 0; i < len; i++) {
        double fir_ele = expand_mat[i][i];
        for (int j = 0; j < len * 2; j++) {
            expand_mat[i][j] /= fir_ele;  // 该行所有元素除以首元素 //
        }
        for (int m = 0; m < len; m++) {
            if (m == i) {
                continue;
            }
            // 倍数 //
            double times = expand_mat[m][i];
            for (int n = 0; n < len * 2; n++) {
                expand_mat[m][n] -= expand_mat[i][n] * times;
            }
        }
    }
}


// get res
void getNewMatrix(double ** expand_mat, double ** new_mat, int len) {
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < len * 2; j++) {
            if (j >= len) {
                new_mat[i][j - len] = expand_mat[i][j];
            }
        }
    }
}


// print matrix
void printMatrix(double** mat, int len) {
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < len; j++) {
            printf("%.1lf ", mat[i][j]);
        }
        putchar('\n');
    }
    putchar('\n');
}

// matrix multiplying
double** getProductMatrix(double** init_mat, double** new_mat, int len) {
    double** product_mat = (double**)malloc(sizeof(double*) * len);
    for (int i = 0; i < len; i++) {
        product_mat[i] = (double*)malloc(sizeof(double) * len);
    }
    // need initializing to zero
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < len; j++) {
            product_mat[i][j] = 0;
        }
    }
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < len; j++) {
            for (int k = 0; k < len; k++) {
                product_mat[i][j] += init_mat[i][k] * new_mat[k][j];
            }
        }
    }
    return product_mat;
}
  • 示例测试结果
    C语言实现 求解逆矩阵_第1张图片
    C语言实现 求解逆矩阵_第2张图片
  • 每一个不曾起舞的日子,都是对生命的辜负。

你可能感兴趣的:(算法,c语言,矩阵,线性代数,算法)