C语言求矩阵的逆(伴随法)

article/2025/9/23 3:18:58

之前介绍了C语言用代数余子式求行列式

本次开始介绍如何用公式法对矩阵求逆,并用C语言将其实现。

之前程序有点小bug,已于2022年11月29日修改。

更新:

        伴随法只适合求低阶矩阵的逆,对于相对高阶(20维以上)对矩阵求逆用高斯法求解效率更高,此外本文中使用了_msize函数用于判断内存维数,但该函数只适合winodows系统,Linux和Mac系统无法使用(笔者也是在用了Mac系统后才发现),对于上述两个问题,您应该可以在:C语言求矩阵的逆(高斯法)得到满意的答案。

        如果矩阵接近奇异值,求逆的数值将不稳定,那么使用C语言LU分解法求逆将会得到更好的效果。

目录

数学原理

矩阵求逆的公式

数乘矩阵 

程序设计

整体代码

求行列式的值(Det、Cof)

求伴随矩阵(FindCof)

求逆矩阵的主函数(matrix_inver)

测试


数学原理

矩阵求逆的方法有很多种,本次主要介绍如何利用公式法求解。

矩阵求逆的公式

A^{-1}=\frac{1}{\left | A \right |}A^{*}

其中,\left | A \right |为A的行列式的值,A^{*}为矩阵A的伴随矩阵。

伴随矩阵的表达方式为:

A_{ij}^{*}=\begin{bmatrix} A_{11} &A_{12} &... &A_{1j} \\ A_{21}&A_{22} & ... & ...\\ ... &... & ...& ..\\ A_{i1} &A_{i2} &.. & A_{ij} \end{bmatrix}^{T}

其中,A_{ij}为代数余子式,代数余子式A_{ij}与余子式M_{ij}的关系为:

A_{ij}=\left ( -1 \right )^{i+j}M_{ij}

M_{ij}是矩阵A去掉i行j列,剩下元素重新组成的新矩阵 。

数乘矩阵 

假设矩阵A为:

A=\begin{bmatrix} a_{11} &a_{12} &a_{13} \\ a_{21}& a_{22} & a_{23}\\ a_{31}& a_{32} & a_{33} \end{bmatrix}

如果一个数b乘以一个矩阵A,那么A中的每一个元素都要乘以b,其表示如下: 

bA=\begin{bmatrix} ba_{11} &ba_{12} &ba_{13} \\ ba_{21}& ba_{22} & ba_{23}\\ ba_{31}& ba_{32} & ba_{33} \end{bmatrix}

程序设计

为了后面方便调试,先利用malloc函数创建一个矩阵,并为其赋值。关于malloc函数有不理解的可以参考之前写的C语言动态内存管理。

malloc使用的基本方式:

  • void* malloc (size_t size);
  • void free (void* ptr);
  • size是指定的开辟内存的大小,单位是字节
  • size_t的无符号整型则限制程序员误操作开辟负字节的空间
  • 如果开辟成功,malloc会返回一个void*类型的指针
  • 如果开辟失败,则返回的是空指针,所以在malloc之后需要对指针进行检查
  • 当malloc的东西不再使用时,需要free对其进行释放,否则会造成内存泄漏
  • malloc和free均需要包含头文件<stdlib.h>
//创建n维矩阵空间,并初始化
double** test1(int n)
{double** arr = (double**)malloc(sizeof(double*) * n);int i, j;if (arr != NULL){for (i = 0; i < n; i++){arr[i] = (double*)malloc(sizeof(double) * n);}//为矩阵赋值if (*arr != NULL){for (i = 0; i < n; i++){for (j = 0; j < n; j++){arr[i][j] = pow(i, j);}}}}return arr;
}

其中:

  • double** arr = (double**)malloc(sizeof(double*) * n);表示开辟n个double*类型的空间,将其地址赋给arr
  • 然后再开辟n个double类型的空间,将其地址赋给double**中每个double*
  • 配合下图更好理解

整体代码

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
#include<string.h>#define MatMax 20//函数声明
double Det(const double arr[MatMax][MatMax], int n);
double Cof(const double arr[MatMax][MatMax], int i, int n);
void FindCof(double arr[MatMax][MatMax], double arr2[MatMax][MatMax], int i, int j, int n);
double** matrix_inver(double** arr);//计算行列式
double Det(const double arr[MatMax][MatMax], int n)
{assert(n > 0);double sum = 0;int i = 0;if (n == 1)//1阶行列式直接得出结果{sum = arr[0][0];}else if (n == 2){sum = arr[0][0] * arr[1][1] - arr[0][1] * arr[1][0];//杀戮法求解}else if (n == 3){sum = arr[0][0] * arr[1][1] * arr[2][2]+ arr[0][1] * arr[1][2] * arr[2][0]+ arr[1][0] * arr[2][1] * arr[0][2]- arr[0][2] * arr[1][1] * arr[2][0]- arr[0][1] * arr[1][0] * arr[2][2]- arr[1][2] * arr[2][1] * arr[0][0];//划线法求解}else{for (i = 0; i < n; i++)//按第一行展开{if (arr[0][i] != 0)//展开项不为0才计算{sum += ((int)pow(-1, i + 0)) * arr[0][i] * (Cof(arr, i, n));//2阶以上继续递归		}elsesum += 0;//展开项为0}}return sum;
}
//找到余子式
double Cof(const double arr[MatMax][MatMax], int i, int n)
{assert(n > 0);int k = 0;int j = 0;double arr2[MatMax][MatMax] = { 0 };for (k = 0; k < n - 1; k++)//去除0行i列,剩下的组成新的矩阵{for (j = 0; j < n - 1; j++){if (j < i){arr2[k][j] = arr[k + 1][j];}else{arr2[k][j] = arr[k + 1][j + 1];}}}return Det(arr2, n - 1);
}
//找到去掉i行j列的余子式
void FindCof(double arr[MatMax][MatMax], double arr2[MatMax][MatMax], int i, int j, int n)
{int m = 0;int k = 0;for (m = 0; m < n - 1; m++){for (k = 0; k < n - 1; k++){if (k < j){if (m < i){arr2[m][k] = arr[m][k];}else{arr2[m][k] = arr[m + 1][k];}}else{if (m < i){arr2[m][k] = arr[m][k + 1];}else{arr2[m][k] = arr[m + 1][k + 1];}}}}
}//计算逆的主函数
double** matrix_inver(double** arr)
{int i, j, n;double** res=NULL;n = (int)_msize(arr) / (int)sizeof(double*);res = (double**)malloc(sizeof(double*) * n);if (res == NULL)exit(-1);for (i = 0; i < n; i++){res[i] = (double*)malloc(sizeof(double) * n);memset(res[i], 0, sizeof(double) * n);}double tmp[MatMax][MatMax] = { 0 };//保护arr,将arr指向内存的数据拷贝到tmp二维数组中for (i = 0; i < n; i++){memcpy(tmp[i],arr[i],sizeof(double) * n);}double a = 1.0 / (Det(tmp, n));for (i = 0; i < n; i++){for (j = 0; j < n; j++){double tmp2[MatMax][MatMax] = { 0 };FindCof(tmp, tmp2, j, i, n);//求转置后的伴随double b = pow(-1, i + j) * Det(tmp2, n - 1);res[i][j] = a * b;}}return res;
}

接下来针对上述代码进行讲解

求行列式的值(Det、Cof)

通过观察发现,利用公式法求矩阵的逆离不开求行列式的值。我们创建两个函数DetCof2

利用代数余子式的方法求解行列式:

Det:求解行列式的主函数,判断行列式的维数,如果维数大于3则进行代数余子式计算,按第一行展开,将其传给Cof函数;如果小于等于3则直接求解,避免过度递归。

Cof:求余子式,将新的余子式传给Det函数。

行列式的计算在这篇博客中C语言计算行列式

求伴随矩阵(FindCof)

该函数与cof函数类似,都是求余子式的,区别在于:

  • FindCoi是找到去掉第i行第j列的余子式;Cof函数固定从第1行第j列
  • FindCof函数不参与递归,只要找到余子式即可

其中:

  • if部分是用来判断组成新的行列式的位置

求逆矩阵的主函数(matrix_inver)

对照之前的公式,对n维的方阵,其伴随矩阵需要求解n*n个代数余子式,利用两个for循环逐行逐列进行处理。

主要思想:

  • 计算行列式的值a,计算1/a
  • 从i行j列开始,求代数余子式,并将求得的余子式部分传给Det函数,计算其行列式的值b
  • 计算a*b,并赋值

主函数中:

  •  n = (int)_msize(arr) / (int)sizeof(double*);求矩阵的维数,_msize是库函数,需要包含头文件:<malloc.h>求其指针指向地址的内存大小,单位是字节;对照res开辟内存的过程,即可明白其计算原理。
  • memcpy(tmp[i],arr[i],sizeof(double) * n);进行内存拷贝,将动态内存中数据拷贝到二维数组中。有两层意义:一:防止递归中造成内存泄漏;二:保护原矩阵

测试

int main()
{int n = 5;double** arr = test1(n);printf("原矩阵:>\n");print(arr);double** res = matrix_inver(arr);printf("逆矩阵:>\n");print(res);return 0;
}

其中: 

  • test1是上述创建矩阵的函数
  • print是用来打印矩阵的函数,代码如下:
//打印矩阵
void print(double** arr)
{putchar('\n');int i, j, row, col;row = (int)_msize(arr) / (int)sizeof(double*);//判断行数col = (int)_msize(*arr) / (int)sizeof(double);//判断列数for (i = 0; i < row; i++){for (j = 0; j < col; j++){printf("%10.5lf ", arr[i][j]);}putchar('\n');}putchar('\n');
}

测试结果如下: 

与matlab计算的结果进行比对:

 如果矩阵治亏,则会输出:

因为公式法涉及到递归,因此无法计算高维逆矩阵,想要保证精度和效率,可以尝试利用LU分解法进行矩阵求逆,这也是目前大多数计算机在处理高维矩阵时的策略。


http://chatgpt.dhexx.cn/article/xUDT7Imb.shtml

相关文章

C语言 矩阵乘法

Description 给出m * n阶矩阵A&#xff0c;乘以n * p阶的矩阵B&#xff0c;得到一个m*p阶的矩阵C。矩阵乘法定义如下图所示。 Input 输入分为两部分&#xff1a;第一部分是三个整数m、n和p&#xff1b;后面为两个矩阵&#xff0c;分别是mn阶矩阵A和np阶矩阵B。m、n和p都不会超…

C语言矩阵库------Matrix

欢迎使用Matrix Matrix目前能实现矩阵的基本功能,例如:方阵行列式求解,矩阵的线性运算和矩阵相乘,矩阵求逆等等. 我会持续更新此库,需要的朋友可以进行下载。 V1.1版本10阶矩阵的行列式和逆矩阵求解对齐了matlab的精度&#xff0c;但是速度较慢。谨慎使用于高阶矩阵运算。 链…

使用C语言实现矩阵转置(稀疏矩阵)

目录 1.转置矩阵&#xff08;普通矩阵&#xff09; 2.转置矩阵&#xff08;稀疏矩阵&#xff09; &#xff08;1&#xff09;稀疏矩阵 &#xff08;2&#xff09;稀疏矩阵的压缩存储方式 &#xff08;3&#xff09;理论运算方法 1.转置矩阵&#xff08;普通矩阵&#xff0…

c语言矩阵

思路&#xff1a;开辟一个新的同样规格的矩阵b&#xff0c;并将其全部置1. 遍历矩阵a(原矩阵)&#xff0c;发现有0的就在b的此行此列中插入0 // // main.c // test // // Created by 神威 on 2018/9/11. // Copyright © 2018年 神威. All rights reserved. // #incl…

C语言-矩阵转置

描述 KiKi有一个矩阵&#xff0c;他想知道转置后的矩阵&#xff08;将矩阵的行列互换得到的新矩阵称为转置矩阵&#xff09;&#xff0c;请编程帮他解答。 输入描述&#xff1a; 第一行包含两个整数n和m&#xff0c;表示一个矩阵包含n行m列&#xff0c;用空格分隔。 (1≤n≤…

C语言对矩阵进行转置

对矩阵进行转置最重要的是值的交换&#xff0c;这里用到了二重数组 #include <stdio.h> #include <stdlib.h>int main() {int a[3][3]{1,2,3,4,5,6,7,8,9};//初始化一个矩阵出来int b[3][3]{0};for(int i0;i<2;i){for(int k0;k<2;k){b[k][i]a[i][k];//对矩…

C语言 - 矩阵转置

C语言 - 矩阵转置 输入NM的矩阵&#xff0c;输出它的转置矩阵。 Input 第一行为整数N&#xff0c;M&#xff08;1≤N&#xff0c;M≤100&#xff09;。 接着是一个NM的矩阵。 Output 转置矩阵。 Example Input 2 3 1 2 3 4 5 6 Example Output 1 4 2 5 3 6#include&l…

(C语言)求矩阵各行元素之和

本题来自pintia.cn 题目要求代码测试结果图PTA测试结果 题目要求 本题要求编写程序&#xff0c;求一个给定的mn矩阵各行元素之和。 输入格式&#xff1a; 输入第一行给出两个正整数m和n&#xff08;1≤m,n≤6&#xff09;。随后m行&#xff0c;每行给出n个整数&#xff0c;其间…

编写矩阵运算程序(C语言)

编写矩阵运算程序之C语言 1. 要求2 代码 1. 要求 a) 功能包括&#xff1a;矩阵加、矩阵减、矩阵乘、矩阵三角化 b) 实现方式1&#xff1a;函数的参数为&#xff1a;二维数组名、行数、列数 2 代码 #include<stdio.h> #define M 20 #define N 20 float A[M][N]; float…

C语言——矩阵转置

矩阵转置的原理&#xff1a;行元素变成列元素&#xff0c;列元素变成行元素 例如&#xff1a; 矩阵转置代码 #include<stdio.h> #include<malloc.h> #include<stdlib.h> #include<math.h>//矩阵转置 double** Matrix_T(double** arr) {if(arrNULL)e…

C语言实现矩阵的乘法

矩阵乘法作为算法题我觉得对我来说是比较难想的&#xff0c;而且作为没学线性代数的我来说&#xff0c;这简直就是场灾难&#xff0c;在我研究了书上及网上的有关资料后&#xff0c;我觉得自己应该差不多可以理解矩阵乘法的要领了&#xff0c;希望可以帮助大家&#xff1a;其实…

C语言矩阵运算

矩阵的乘法&#xff1a; 矩阵的列数&#xff08;column&#xff09;和第二个矩阵的行数&#xff08;row&#xff09;相同时 #include<stdio.h>int main() { int a[2][4], b[4][3], c[2][3];int i, j, k, sum; printf("输入一个24的矩阵&#xff1a;\n"); fo…

c语言矩阵的乘法

矩阵的乘法&#xff1a; 两个矩阵只有在第一个矩阵的列数&#xff08;column&#xff09;和第二个矩阵的行数&#xff08;row&#xff09;相同时才有意义。一般单指矩阵乘积时&#xff0c;指的便是一般矩阵乘积。一个mn的矩阵就是mn个数排成m行n列的一个数阵。 运算规则&#x…

C语言刷题小结---矩阵篇

电影黑客帝国有很多这样的场景 用矩阵表示我们看到的一切&#xff01; 而在编程中矩阵是用数组来表示的 目前小作者还只是学习编程的初学者&#xff0c;很多知识内容都还没有学习。但相信每一个学习编程的小伙伴在做C语言方面的练习时都会遇到有关矩阵相关的题目&#xff0c;…

《C语言》矩阵问题

一.矩阵乘法 1.定理&#xff1a; 两个矩阵的乘法仅当第一个矩阵A的列数和另一个矩阵B的行数相等时才能定义。如A是mn矩阵和B是np矩阵&#xff0c;它们的乘积C是一个mp矩阵。 例如&#xff1a; 2.思路 1. i&#xff0c;j分别代表行和列&#xff0c;所以应该定义一个二维矩阵&…

C语言矩阵乘法

本篇内容 1&#xff09;首先介绍了矩阵乘法的基本原理&#xff1b; 2&#xff09;然后介绍了相对初阶的C语言乘法代码设计&#xff1b; 3&#xff09;最后根据C语言动态内存规划&#xff0c;提出了更加便捷、优化的代码设计&#xff0c;希望能给大家带来帮助。 更新&#xff1a…

c语言之矩阵

矩阵作为线性代数核心内容之一也是刷题人时常会遇到的一种类型。本篇博客简单介绍一下矩阵转置、上三角矩阵以及杨氏矩阵。 1.转置矩阵&#xff1a;输入m行n列的矩阵以n行m列的方式打印出来。只要将数组的行列进行交换即可&#xff0c;并不难想也不难写.&#xff08;相应练习&a…

vue-quill-editor 使用-图片上传

vue 项目开发中&#xff0c;文本编辑器的选择很多&#xff0c;一些熟悉的文本编辑器都可以使用&#xff0c;如UEditor、wangEditor&#xff0c;这里介绍基于 vue 的一个文本编辑器插件 vue-quill-editor 此插件基于 quill&#xff0c;所以使用 cdn 节点方式引用时&#xff0c;…

Error: Cannot find module ‘./XXX.jpg‘ 问题解决 Vue动态显示图片

刚开始学习Vue 在循环输出图片时&#xff0c;浏览器报错Error: Cannot find module ‘./tqwl.jpg’ 这张图片是放在本地文件夹内的 这是图片的展示代码 <el-table-column label"展示" width"180"><template slot-scope"scope"><…