C语言实现 求解逆矩阵

C语言实现 求解逆矩阵

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

算法思路

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

实现代码

#include <stdio.h>
#include <stdlib.h>

#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;
}
  • 示例测试结果
    在这里插入图片描述
    在这里插入图片描述
  • 每一个不曾起舞的日子,都是对生命的辜负。
  • 7
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
矩阵逆是一个比较复杂的数学问题,需要使用高级的数学算法。在C语言中,可以使用第三方库来实现矩阵逆的功能。 一个比较常用的矩阵逆的库是LAPACK(Linear Algebra Package),它提供了一系列的线性代数运算函数。使用LAPACK库可以比较方便地实现矩阵逆的功能。 下面是一个使用LAPACK库实现矩阵逆的示例代码: ```c #include <stdio.h> #include <lapacke.h> void print_matrix(int m, int n, double *a, int lda) { int i, j; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { printf("%lf ", a[i * lda + j]); } printf("\n"); } } int main() { double a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 10}; int n = 3, lda = 3, ipiv[3], info; // 打印原始矩阵 printf("原始矩阵:\n"); print_matrix(n, n, a, lda); // 计算矩阵的LU分解 info = LAPACKE_dgetrf(LAPACK_ROW_MAJOR, n, n, a, lda, ipiv); if (info != 0) { printf("计算LU分解失败!\n"); return -1; } // 计算矩阵的逆 info = LAPACKE_dgetri(LAPACK_ROW_MAJOR, n, a, lda, ipiv); if (info != 0) { printf("计算矩阵逆失败!\n"); return -1; } // 打印矩阵逆 printf("矩阵逆:\n"); print_matrix(n, n, a, lda); return 0; } ``` 在上面的代码中,我们首先定义了一个3x3的矩阵a,然后通过LAPACK库中的dgetrf和dgetri函数来计算矩阵的LU分解和逆矩阵。最后打印出计算得到的逆矩阵。 需要注意的是,使用LAPACK库需要在编译时链接相应的库文件。在Linux系统中,可以使用以下命令来编译上面的代码: ```bash gcc -o matrix_inverse matrix_inverse.c -llapacke -llapack -lblas -lm ``` 其中,-llapacke,-llapack,-lblas,-lm分别表示链接LAPACK库、BLAS库和数学库。在Windows系统中,链接方式可能略有不同,需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_廿_尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值