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;
                    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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity Shader

练习项目链接 1. Shader 介绍 Shader其实就是专门用来渲染图形的一段代码&#xff0c;通过shader&#xff0c;可以自定义显卡渲染画面的算法&#xff0c;使画面达到我们想要的效果。小到每一个像素点&#xff0c;大到整个屏幕&#xff0c;比如下面这个比较常见的效果。 2. Sh…

javaSwing宿舍管理系统(三个角色)

一、 简介 宿舍管理系统是一个针对学校宿舍管理的软件系统&#xff0c;旨在方便学生、宿管和管理员进行宿舍信息管理、学生信息管理以及宿舍评比等操作。该系统使用 Java Swing 进行界面设计&#xff0c;分为三个角色&#xff1a;管理员、宿管和学生。 二、 功能模块 2.1 管…

RK3568平台 iperf3测试网络性能

一.iperf3简介 iperf是一款开源的网络性能测试工具&#xff0c;主要用于测量TCP和UDP带宽性能。它可以在不同的操作系统上运行&#xff0c;包括Windows、Linux、macOS等。iperf具有简单易用、功能强大、高度可配置等特点&#xff0c;广泛应用于网络性能测试、网络故障诊断和网…

深度学习绘制热力图heatmap、使模型具有可解释性

思路 获取想要解释的那一层的特征图&#xff0c;然后根据特征图梯度计算出权重值&#xff0c;加在原图上面。 Demo 加上类激活(cam) 可以看到&#xff0c;cam将模型认为有利于分类的特征标注了出来。 下面以ResNet50为例: Trick: 使用 for i in model._modules.items():可以…

二十三 超级数据查看器 讲解稿 设置

二十三 超级数据查看器 讲解稿 设置 ​点击此处 以新页面 打开B站 播放当前教学视频 点击访问app下载页面 百度手机助手 下载地址 大家好&#xff0c;这节课我们讲一下&#xff0c;超级数据查看器的设置功能。 首先&#xff0c;我们打开超级数据查看器&#xff0c; 我…

2023年全国青少年信息素养大赛(python)初赛真题

选择题&#xff08;每题5分&#xff0c;共20题&#xff0c;满分100分&#xff09; 1、关于列表的索引&#xff0c;下列说法正确的是&#xff1f; A&#xff0e;列表的索引从0开始 B&#xff0e;列表的索引从1开始 C&#xff0e;列表中可能存在两个元素的索引一致 D&#xff0…

第四百一十九回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"自定义标题栏"相关的内容&#xff0c;本章回中将介绍自定义Action菜单.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里提到的…

web自动化3-pytest前后置夹具

一、pytest前后置&#xff08;夹具&#xff09;-fixture 夹具的作用&#xff1a;在用例执行之前和之后&#xff0c;需要做的准备工作和收尾工作。 用于固定测试环境&#xff0c;以及清理回收资源。 举个例子&#xff1a;访问一个被测页面-登录页面&#xff0c;执行测试用例过…

SpringCloud-Gateway服务网关

一、网关介绍 1. 为什么需要网关 Gateway网关是我们服务的守门神&#xff0c;所有微服务的统一入口。 网关的核心功能特性&#xff1a; 请求路由 权限控制 限流 架构图&#xff1a; 权限控制&#xff1a;网关作为微服务入口&#xff0c;需要校验用户是是否有请求资格&am…

算法-双指针

目录 1、双指针遍历分割:避免开空间&#xff0c;原地处理 2、快慢指针&#xff1a;循环条件下的判断 3、左右指针&#xff08;对撞指针&#xff09;&#xff1a;分析具有单调性&#xff0c;避免重复计算 双指针又分为双指针遍历分割&#xff0c;快慢指针和左右指针 1、双指…

深度学习 tablent表格识别实践记录

下载代码&#xff1a;https://github.com/asagar60/TableNet-pytorch 下载模型&#xff1a;https://drive.usercontent.google.com/download?id13eDDMHbxHaeBbkIsQ7RSgyaf6DSx9io1&exportdownload&confirmt&uuid1bf2e85f-5a4f-4ce8-976c-395d865a3c37 原理&#…

C# 将 Word 转文本存储到数据库并进行管理

目录 功能需求 范例运行环境 设计数据表 关键代码 组件库引入 Word文件内容转文本 上传及保存举例 得到文件Byte[]数据方法 查询并下载Word文件 总结 功能需求 将 WORD 文件的二进制信息存储到数据库里&#xff0c;即方便了统一管理文件&#xff0c;又可以实行权限控…

查看文件内容的指令:cat,tac,nl,more,less,head,tail,写入文件:echo

目录 cat 介绍 输入重定向 选项 -b -n -s tac 介绍 输入重定向 nl 介绍 示例 more 介绍 选项 less 介绍 搜索文本 选项 head 介绍 示例 选项 -n tail 介绍 示例 选项 echo 介绍 输出重定向 追加重定向 cat 介绍 将标准输入(键盘输入)的内容打…

【微服务】Gateway服务网关

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;微服务 ⛺️稳中求进&#xff0c;晒太阳 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等响…

单目深度估计基础理论和论文学习总结

单目深度估计基础理论和论文学习总结 一、背景知识&#xff1a; 三维刚体运动的数学表示&#xff1a;旋转平移矩阵、旋转向量、欧拉角、四元数、轴角模型、齐次坐标、各种变换等 照相机模型&#xff1a;单目/双目模型&#xff0c;单目中的世界坐标系/相机坐标系/图像坐标系的…

MySQL表的增删改查---多表查询和联合查询

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

保研复习概率论1

1.什么是随机试验&#xff08;random trial&#xff09;&#xff1f; 如果一个试验满足试验可以在相同的条件下重复进行、试验所有可能结果明确可知&#xff08;或者是可知这个范围&#xff09;、每一次试验前会出现哪个结果事先并不确定&#xff0c;那么试验称为随机试验。 …

ssm+vue的消防物资存储系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的消防物资存储系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

PyQT5学习--新建窗体模板

目录 1 Dialog 2 Main Window 3 Widget Dialog 模板&#xff0c;基于 QDialog 类的窗体&#xff0c;具有一般对话框的特性&#xff0c;如可以模态显示、具有返回值等。 Main Window 模板&#xff0c;基于 QMainWindow 类的窗体&#xff0c;具有主窗口的特性&#xff0c;窗口…

重生奇迹mu弓箭手技能

1、弓箭手职业技能&#xff1a;多重箭&#xff1a;同时射出三发弓箭&#xff0c;给予复数敌人伤害&#xff0c;根据弓的不同&#xff0c;射出的数量也不同。天堂之箭&#xff1a;弓箭垂直射向天际&#xff0c;准确的落在敌人的头顶上&#xff0c;造成严重的伤害。 2、连技技能…