c#矩阵求逆

2024-03-24 15:52
文章标签 c# 矩阵 .net netcore 求逆

本文主要是介绍c#矩阵求逆,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、矩阵求逆的数学方法

1、伴随矩阵法

2、初等变换法

3、分块矩阵法

4、定义法

二、矩阵求逆C#代码

1、伴随矩阵法求指定3*3阶数矩阵的逆矩阵

(1)伴随矩阵数学方法

(2)代码

(3)计算

2、对任意阶数矩阵求逆

(1)计算方法

(2)代码

(3)计算

(4)计算结果

三、工程下载连接


一、矩阵求逆的数学方法

1、伴随矩阵法

2、初等变换法

3、分块矩阵法

4、定义法

二、矩阵求逆C#代码

1、伴随矩阵法求指定3*3阶数矩阵的逆矩阵

(1)伴随矩阵数学方法

(2)代码

        /// <summary>/// 计算3*3矩阵的逆矩阵/// </summary>/// <param name="input">输入的3*3矩阵</param>/// <returns>计算得到的3*3逆矩阵</returns>public static double[,] inv3(double[,] input){double[,] output = new double[3, 3];//求出伴随矩阵output[0, 0] = input[2, 2] * input[1, 1] - input[2, 1] * input[1, 2];output[0, 1] = input[2, 1] * input[0, 2] - input[0, 1] * input[2, 2];output[0, 2] = input[0, 1] * input[1, 2] - input[0, 2] * input[1, 1];output[1, 0] = input[1, 2] * input[2, 0] - input[2, 2] * input[1, 0];output[1, 1] = input[2, 2] * input[0, 0] - input[0, 2] * input[2, 0];output[1, 2] = input[0, 2] * input[1, 0] - input[0, 0] * input[1, 2];output[2, 0] = input[1, 0] * input[2, 1] - input[2, 0] * input[1, 1];output[2, 1] = input[2, 0] * input[0, 1] - input[0, 0] * input[2, 1];output[2, 2] = input[0, 0] * input[1, 1] - input[1, 0] * input[0, 1];//求出行列式的值double Avalue = input[0, 0] * input[1, 1] * input[2, 2]+ input[0, 1] * input[1, 2] * input[2, 0]+ input[0, 2] * input[1, 0] * input[2, 1]- input[0, 2] * input[1, 1] * input[2, 0]- input[0, 1] * input[1, 0] * input[2, 2]- input[0, 0] * input[1, 2] * input[2, 1];//求出 逆矩阵 for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){output[i, j] = output[i, j] / Avalue;}}return output;}

(3)计算

计算代码

            计算3*3矩阵的逆矩阵double[,] input = new double[3, 3] {{ 0,    1,      3 }, { 1,    -1,     0 },{-1,    2,      1}};double[,] out1 = inv3(input);               //方法1——只能求3*3

程序计算结果

对应数学题目

2、对任意阶数矩阵求逆

(1)计算方法

Step1

1)利用初等行变换,那么要将单位矩阵E和n阶矩阵B合并(规定为EandB_normal[ n, 2 * n])

Step2

2)将EandB_normal[ n, 2 * n]转为右半部分为上三角的矩阵

>>>这一步转换比较复杂一点,具体实现就是:

>>>第一层循环,循环变量 j 从第n列开始到第2 * n - 1列结束,目的就是将该列值都转为1,方便后边变为上三角矩阵(需要注意的是,对于第n列,应该考虑把每个值都变为1;但是到第n + 1列时,就不考虑第一个值了;第n + 2列时,不考虑第一个和第二个值;类推);

>>>第二层循环,循环变量 i 从第j - n行开始到第n - 1行结束,目的是对每一行都进行除以EandB_normal[ i, j]值的运算,这样EandB_normal[ i, j]的值就变为了1(需要注意的是,如果EandB_normal[ i, j]的值为0的话,我们考虑将该行与最后一行调换,同时循环变量 i 到第n - 2行结束;如果调换之后,EandB_normal[ i, j]的值仍然为0,那么再将该行与此时的最后一行调换,类推;但是如果一直调换,直到发现始终为0,就说明矩阵B不满秩,退出计算;如果EandB_normal[ i, j]值为负数,该行同时变号);

>>>第三层循环,循环变量 k 从第0列开始到第2 * n - 1列结束,目的是将上一步中循环到的行中的每一个值都除以EandB_normal[ i, j]的值;

>>>循环全部完成之后,矩阵EandB_normal[ n, 2 * n]就变成了右半部分为上三角的矩阵。

Step3

3)接上一步,将该矩阵转为右半部分为单位矩阵的矩阵,此时即为矩阵B的逆矩阵与单位矩阵的合并(规定为B_inverse_andE[ n, 2 * n])

>>>这一步中的循环变量是递减的,具体实现就是:

>>>第一层循环,循环变量 j 从第2 * n - 1列开始到第n列结束,目的是将该列值只保留一个1,其余变为0;

>>>第二层循环,循环变量 i 从第 j - n行开始到第0行结束;

>>>第三层循环,循环变量 k 从第0列开始到第2 * n - 1列结束;拿 j = 2 * n - 1, i = n - 1举例,此时,我们希望第n - 2行的值都加上该行最后一个值的相反数与第n - 1行乘积的对应值,第n - 3行的值都加上该行最后一个值得相反数与第n - 1行乘积的对应值,类推;(需要注意的是,j = 2 * n - 2时,i从第n - 2行开始循环,j = 2 * n - 3时,i从第n - 2行开始循环,类推);

>>>当循环全部完成之后,B_inverse_andE[ n, 2 * n]的右半部分就变为了单位矩阵,左半部分为矩阵B的逆矩阵。

Step4

4)接上一步,将B的逆矩阵取出来(规定为B_inverse[n, n])

(2)代码

/// <summary>/// 任意矩阵求逆。(矩阵是2*2、3*3、4*4、5*5等类型)/// </summary>/// <param name="matrixB">输入的初始矩阵</param>/// <param name="orderNum">矩阵行和列的数</param>/// <returns>计算出的逆矩阵</returns>public static double[,] MatrixInverse(double[,] matrixB, int orderNum){//判断是否满秩bool IsFullRank = true;//n为阶级int n = orderNum;//####赋值####//矩阵B//矩阵B的逆矩阵//单位矩阵E和矩阵B组成的矩阵double[,] B_normal = matrixB;double[,] B_inverse = new double[n, n];double[,] EandB_normal = new double[n, 2 * n];for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){if (i == j)EandB_normal[i, j] = 1;elseEandB_normal[i, j] = 0;}for (int k = n; k < 2 * n; k++){EandB_normal[i, k] = B_normal[i, k - n];}}//####计算####//中间变量数组,用于临时盛装值double[] rowHaveZero = new double[2 * n];//EB矩阵右边的n*n变为上三角矩阵for (int j = n; j < 2 * n; j++){int firstRowN = j - n;int lastRowN = n;int colCount = 2 * n;//把EB中索引为j的列的值化为1for (int i = firstRowN; i < lastRowN; i++){//如果EBijNum值为0,就把0所在的行与此刻最后一行调换位置//并且循环变量i的终止值减去1,直到EBijNum值不为0//最多调换到0所在的行的下一行double EBijNum = EandB_normal[i, j];while (EBijNum == 0 && lastRowN > i + 1){for (int k = 0; k < colCount; k++){rowHaveZero[k] = EandB_normal[i, k];EandB_normal[i, k] = EandB_normal[lastRowN - 1, k];EandB_normal[lastRowN - 1, k] = rowHaveZero[k];}lastRowN -= 1;EBijNum = EandB_normal[i, j];}//如果while循环是由第二个判断跳出//即EBijNum始终为0if (EBijNum == 0){//循环变量i的终止值再减去1,然后跳出循环lastRowN -= 1;break;}//如果为负数,该行变号if (EBijNum < 0){for (int k = 0; k < colCount; k++){EandB_normal[i, k] = (-1) * EandB_normal[i, k];}EBijNum = EandB_normal[i, j];}//将该值变为1,则其余值都除以EBijNumfor (int k = 0; k < colCount; k++){EandB_normal[i, k] = EandB_normal[i, k] / EBijNum;}}//自n列起,每列只保留一个1,呈阶梯状int secondRowN = firstRowN + 1;for (int i = secondRowN; i < lastRowN; i++){for (int k = 0; k < colCount; k++){EandB_normal[i, k] = EandB_normal[i, k]- EandB_normal[firstRowN, k];}}if (lastRowN == firstRowN){//矩阵不满秩IsFullRank = false;break;}}//不满秩,结束运算if (!IsFullRank){double[,] error = new double[n, n];for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){error[i, j] = 0;}}//返还值均为0的矩阵return error;}//将上三角矩阵变为单位矩阵for (int j = 2 * n - 1; j > n; j--){//firstRowN为参考行//secondRowN为运算行int firstRowN = j - n;int secondRowN = firstRowN - 1;int colCount = j + 1;//从最后一列起,每列只保留一个1,其余减为0for (int i = secondRowN; i > -1; i--){double EBijNum = EandB_normal[i, j];for (int k = 0; k < colCount; k++){EandB_normal[i, k] = EandB_normal[i, k]- EandB_normal[firstRowN, k] * EBijNum;}}}//####提取逆矩阵####for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){B_inverse[i, j] = EandB_normal[i, j];}}return B_inverse;}

(3)计算

private void button1_Click(object sender, EventArgs e){计算3*3矩阵的逆矩阵double[,] input = new double[3, 3] {{ 0,    1,      3 }, { 1,    -1,     0 },{-1,    2,      1}};double[,] out1 = inv3(input);               //方法1——只能求3*3double[,] out2 = MatrixInverse(input, 3);   //方法2计算2*2矩阵的逆矩阵double[,] input2 = new double[2, 2] {{ 1, 2 }, { 3, 4 }};double[,] out3 = MatrixInverse(input2, 2); //计算4*4矩阵的逆矩阵double[,] input3 = new double[4, 4] {{ 2, 1,-1,2 }, { 1, 1,1,-1 },{0,0,2,5},{0,0,1,3}};double[,] out4 = MatrixInverse(input3, 4); }

(4)计算结果

以4*4矩阵说明

三、工程下载连接

https://download.csdn.net/download/panjinliang066333/89024543

这篇关于c#矩阵求逆的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/842065

相关文章

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

C#下Newtonsoft.Json的具体使用

《C#下Newtonsoft.Json的具体使用》Newtonsoft.Json是一个非常流行的C#JSON序列化和反序列化库,它可以方便地将C#对象转换为JSON格式,或者将JSON数据解析为C#对... 目录安装 Newtonsoft.json基本用法1. 序列化 C# 对象为 JSON2. 反序列化

C#文件复制异常:"未能找到文件"的解决方案与预防措施

《C#文件复制异常:未能找到文件的解决方案与预防措施》在C#开发中,文件操作是基础中的基础,但有时最基础的File.Copy()方法也会抛出令人困惑的异常,当targetFilePath设置为D:2... 目录一个看似简单的文件操作问题问题重现与错误分析错误代码示例错误信息根本原因分析全面解决方案1. 确保

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

C#高效实现Word文档内容查找与替换的6种方法

《C#高效实现Word文档内容查找与替换的6种方法》在日常文档处理工作中,尤其是面对大型Word文档时,手动查找、替换文本往往既耗时又容易出错,本文整理了C#查找与替换Word内容的6种方法,大家可以... 目录环境准备方法一:查找文本并替换为新文本方法二:使用正则表达式查找并替换文本方法三:将文本替换为图

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点