c#矩阵求逆

news2024/9/27 17:24:27

目录

一、矩阵求逆的数学方法

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;
                    else
                        EandB_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的列的值化为1
                for (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始终为0
                    if (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,则其余值都除以EBijNum
                    for (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,其余减为0
                for (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*3
            double[,] 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1541837.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【科研基础】VAE: Auto-encoding Variational Bayes

[1]Kingma, Diederik P., and Max Welling. “Auto-encoding variational bayes.” arXiv preprint arXiv:1312.6114 (2013). [2] [论文简析]VAE: Auto-encoding Variational Bayes[1312.6114] [3] The Reparameterization Trick 文章目录 1-什么是VAE1.1-目标1.2-Intractab…

阿里云-零基础入门NLP【基于深度学习的文本分类3-BERT】

文章目录 学习过程赛题理解学习目标赛题数据数据标签评测指标解题思路BERT代码 学习过程 20年当时自身功底是比较零基础(会写些基础的Python[三个科学计算包]数据分析)&#xff0c;一开始看这块其实挺懵的&#xff0c;不会就去问百度或其他人&#xff0c;当时遇见困难挺害怕的…

nodejs+vue高校社团管理小程序的设计与实现python-flask-django-php

相比于以前的传统手工管理方式&#xff0c;智能化的管理方式可以大幅降低学校的运营人员成本&#xff0c;实现了高校社团管理的标准化、制度化、程序化的管理&#xff0c;有效地防止了高校社团管理的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能够及时、准…

信号处理--使用EEGNet进行BCI脑电信号的分类

目录 理论 工具 方法实现 代码获取 理论 EEGNet作为一个比较成熟的框架&#xff0c;在BCI众多任务中&#xff0c;表现出不俗的性能。EEGNet 的主要特点包括&#xff1a;1&#xff09;框架相对比较简单紧凑 2&#xff09;适合许多的BCI脑电分析任务 3&#xff09;使用两种卷…

CHAT~(持续更新)

CHAT&#xff08;持续更新&#xff09; 实现一个ChatGPT创建API设计页面布局业务操作技术架构 编码其他 实现一个ChatGPT 创建API 最简单也最需要信息的一步 继续往下做的前提 此处省略&#xff0c;想要获取接口创建方式联系 设计 页面布局 按照官网布局 业务操作 注册登…

Vue 3 + TypeScript + Vite的现代前端项目框架

随着前端开发技术的飞速发展&#xff0c;Vue 3、TypeScript 和 Vite 构成了现代前端开发的强大组合。这篇博客将指导你如何从零开始搭建一个使用Vue 3、TypeScript以及Vite的前端项目&#xff0c;帮助你快速启动一个性能卓越且类型安全的现代化Web应用。 Vue 3 是一款渐进式Jav…

快速入门go语言

环境搭建 编译器安装 1、编译器下载地址 2、打开命令行模式&#xff0c;输入go version ide安装 ide下载地址 依赖管理 goproxy 1、goproxy代理地址 // 阿里云 https://mirrors.aliyun.com/goproxy // 微软 https://goproxy.io // 七牛 https://goproxy.cn 2、ide配置g…

初识 Redis 浅谈分布式

目 录 一.认识 Redis二.浅谈分布式单机架构分布式是什么数据库分离和负载均衡理解负载均衡数据库读写分离引入缓存数据库分库分表引入微服务 三.概念补充四.分布式小结 一.认识 Redis 在 Redis 官网我们可以看到介绍 翻译过来就是&#xff1a;数以百万计的开发人员用作缓存、…

阿里云倚天云服务器怎么样?如何收费?

阿里云倚天云服务器CPU采用倚天710处理器&#xff0c;租用倚天服务器c8y、g8y和r8y可以享受优惠价格&#xff0c;阿里云服务器网aliyunfuwuqi.com整理倚天云服务器详细介绍、倚天710处理器性能测评、CIPU架构优势、倚天服务器使用场景及生态支持&#xff1a; 阿里云倚天云服务…

人工智能之Tensorflow批标准化

批标准化&#xff08;Batch Normalization,BN&#xff09;是为了克服神经网络层数加深导致难以训练而诞生的。 随着神经网络的深度加深&#xff0c;训练会越来越困难&#xff0c;收敛速度会很慢&#xff0c;常常会导致梯度消失问题。梯度消失问题是在神经网络中&#xff0c;当前…

ffmpeg实现媒体流解码

本期主要讲解怎么将MP4媒体流的视频解码为yuv,音频解码为pcm数据;在此之前我们要先了解解复用和复用的概念; 解复用:像mp4是由音频和视频组成的(其他内容流除外);将MP4的流拆分成视频流(h264或h265等)和音频流(AAC或mp3等); 复用:就是将音频和视频打包成MP4或者fl…

数据可视化-ECharts Html项目实战(6)

在之前的文章中&#xff0c;我们学习了如何设置散点图、雷达图。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢数据可视化-ECharts Html项目实战&#xff08;5&a…

网络分类简述与数据链路层协议(PPP)

实验拓扑 实验要求 1、R1和R2使用PPP链路直连&#xff0c;R2和R3把2条PPP链路捆绑为PPP MP直连按照图示配置IP地址 2、R2对R1的PPP进行单向chap验证 3、R2和R3的PPP进行双向chap验证 实验思路 给R1、R2的S3/0/0接口配置IP地址&#xff0c;已给出网段192.168.1.0/24R2作为主…

人工智能之Tensorflow变量作用域

在TensoFlow中有两个作用域&#xff08;Scope&#xff09;&#xff0c;一个时name_scope ,另一个是variable_scope。variable_scope主要给variable_name加前缀&#xff0c;也可以给op_name加前缀&#xff1b;name_scope给op_name加前缀。 variable_scope 通过所给的名字创建或…

分类预测 | Matlab实现MTF-CNN-Mutilhead-Attention马尔可夫转移场卷积网络多头注意力机制多特征分类预测/故障识别

分类预测 | Matlab实现MTF-CNN-Mutilhead-Attention马尔可夫转移场卷积网络多头注意力机制多特征分类预测/故障识别 目录 分类预测 | Matlab实现MTF-CNN-Mutilhead-Attention马尔可夫转移场卷积网络多头注意力机制多特征分类预测/故障识别分类效果基本介绍模型描述程序设计参考…

STM32学习笔记(3_2)- GPIO输入和C语言

无人问津也好&#xff0c;技不如人也罢&#xff0c;都应静下心来&#xff0c;去做该做的事。 最近在学STM32&#xff0c;所以也开贴记录一下主要内容&#xff0c;省的过目即忘。视频教程为江科大&#xff08;改名江协科技&#xff09;&#xff0c;网站jiangxiekeji.com 本期介…

idea maven配置

修改maven的路径&#xff08;使用本地的Maven&#xff09;&#xff0c;以及修改settings文件的位置和本地仓库的位置。 -DarchetypeCataloginternal 配置阿里云镜像&#xff08;在setting.xml文件中配置&#xff09; <!-- 配置阿里云 --> <mirror> <id>…

javase day11笔记

第十一天课堂笔记 构造代码块 { } 给 所有对象 共性特点 进行初始化操作 创建对象时在堆区对象中存放实例变量,同时执行构造代码块 执行顺序:静态代码块—>非静态代码块—>构造方法 继承★★★ 将多个类中相同的实例变量和实例方法 , 单独存放到一个类中,成为父类…

政安晨:【深度学习部署】—— TensorFlow Extended(TFX)介绍

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎机器学习 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 前言 TensorFlow Extended&#xff08;TFX&a…

代数结构与数理逻辑:3.环

图1 环 14.1 环的定义与性质 环&#xff1a;代数系统 [ R ; ; ∗ ] [R;;*] [R;;∗]&#xff0c;其中&#xff0c;*为定义在 R R R上的二元运算&#xff0c;满足下述条件&#xff0c;对任意 a , b , c ∈ R a,b,c\in R a,b,c∈R, ​ 可结合、交换&#xff0c;且有单位元、逆元…