写一个矩阵求逆的类

这篇博客介绍了如何在C#中实现矩阵求逆,对比了初等行列变换法和伴随矩阵法。作者提到初等变换法在某些情况下可能更接近MATLAB的求逆结果。内容包括矩阵求逆的基本概念,初等行列变换法的公式、性质、算法逻辑及代码实现,伴随矩阵法的公式、行列式计算、伴随矩阵求解及代码实现。
摘要由CSDN通过智能技术生成

tip:一些废话实在不想看就直接跳转到 代码实现


 

前言

以下内容主要关于求逆的两种方法:

初等行列变换法
伴随矩阵法

     当矩阵数值足够“变态”时,将初等行列变换法和伴随矩阵法求出的值分别与matlab的inv求出的值进行比较,发现初等行列变换法更接近matlab求出的值(当然不排除我写的伴随矩阵法求逆有错误缘故)。
     姑且片面的认为:初等行列变换法相比伴随矩阵法算出的结果更接近matlab求逆算出的结果



一、矩阵求逆

tip:先搬运一段百度百科上的内容
百度百科

矩阵求逆,即求矩阵的逆矩阵。矩阵是线性代数的主要内容,很多实际问题用矩阵的思想去解既简单又快捷。逆矩阵又是矩阵理论的很重要的内容,逆矩阵的求法自然也就成为线性代数研究的主要内容之一。
设A是数域上的一个n阶方阵,若在相同数域上存在另一个n阶矩B,使得: AB=BA=E。 则我们称B是A的逆矩阵,而A则被称为可逆矩阵。其中,E为单位矩阵。
典型的矩阵求逆方法有:利用定义求逆矩阵、初等变换法伴随阵法、恒等变形法等。

二、初等行列变换法


1、基本公式

初等行变换

tip:请忽视为啥不是虚线,因为不会弄

2、相关性质和定理

性质1:

    把行列式的某一行(列)的倍数加到另一方(列)上,行列式的值不变

定理 1:
      
     n阶矩阵A可逆当且仅当A的标准型是In

定理2:

    可逆矩阵总可以经过一系列初等变换化成单位矩阵


3、算法逻辑

算法逻辑
文字太麻烦了,所以就放了个流程图…还看不懂?再加上一个简单的示例应该能懂了吧,如果还不懂,请原谅我爱莫能助了。


以下图 可逆矩阵 为例 (例题缺少aii=0的情况)

可逆矩阵


初始化成初等行变换矩阵的形式
在这里插入图片描述


第一次循环,第一列左边恰好是 1,X,X 因此这一次循环不会产生变化
注:
假设一个n×n阶可逆矩阵
第一次循环的结果是1,X,X,...
第二次循环最后的结果应该是0,1,X, ...
第三次循环最后的结果应该是0,0,1, ...
每次循环都需要把该列的其他行变换为0
以此类推,第n次循环,第n列第n行为1,其余为0;


第二次循环 (红色表示产生变化的部分)

R2×0.5:
第二次循环中间值
观察上图,a12的值是-1,是a22的-1倍
R1-(-1)×R2:
第二次循环

第三次循环

同理,a13是a33的3倍,a23是a33的2倍
R1-3×R3
R2-2×R3
第三次循环

求逆结果:
求逆结果

4、代码实现


/// <summary>
/// 初等变化法求逆
/// </summary>
/// <param name="matrix"></param>
public static double[,] Inverse(double[,] matrix)
{
   
    //可逆矩阵行列相等
    int n = matrix.GetLength(0);

    //初始化变换矩阵
    double[,] temp = new double[n, 2 * n];
    for (int i = 0; i < n; i++)
    {
   
        for (int j = 0; j < n; j++)
        {
   
            temp[i, j] = matrix[i, j];
            if (i == j)
            {
   
                temp[i, n + j] = 1.0;
            }
            else
            {
   
                temp[i, n + j] = 0.0;
            }
        }
    }

    //按列循环进行
    for (int i = 0
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个基于动态数组的矩阵的实现,包括的构造、析构、拷贝、赋值等基本操作,以及矩阵的按元素加减乘除运算,矩阵的乘法、转置和求逆等运算: ```c++ #include <iostream> #include <vector> using namespace std; class Matrix { private: int row; int col; vector<vector<double>> data; public: // 构造函数 Matrix(int r, int c, double val = 0) { row = r; col = c; data.resize(row, vector<double>(col, val)); } // 拷贝构造函数 Matrix(const Matrix &other) { row = other.row; col = other.col; data = other.data; } // 析构函数 ~Matrix() {} // 赋值运算符 Matrix &operator=(const Matrix &other) { if (this != &other) { row = other.row; col = other.col; data = other.data; } return *this; } // 矩阵按元素加法 Matrix operator+(const Matrix &other) const { if (row != other.row || col != other.col) { throw "矩阵加法维度不匹配!"; } Matrix result(row, col); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { result.data[i][j] = data[i][j] + other.data[i][j]; } } return result; } // 矩阵按元素减法 Matrix operator-(const Matrix &other) const { if (row != other.row || col != other.col) { throw "矩阵减法维度不匹配!"; } Matrix result(row, col); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { result.data[i][j] = data[i][j] - other.data[i][j]; } } return result; } // 矩阵按元素乘法 Matrix operator*(const Matrix &other) const { if (row != other.row || col != other.col) { throw "矩阵乘法维度不匹配!"; } Matrix result(row, col); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { result.data[i][j] = data[i][j] * other.data[i][j]; } } return result; } // 矩阵按元素除法 Matrix operator/(const Matrix &other) const { if (row != other.row || col != other.col) { throw "矩阵除法维度不匹配!"; } Matrix result(row, col); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (other.data[i][j] == 0) { throw "矩阵除法除数不能为0!"; } result.data[i][j] = data[i][j] / other.data[i][j]; } } return result; } // 矩阵乘法 Matrix operator*(const Matrix &other) const { if (col != other.row) { throw "矩阵乘法维度不匹配!"; } Matrix result(row, other.col); for (int i = 0; i < row; i++) { for (int j = 0; j < other.col; j++) { for (int k = 0; k < col; k++) { result.data[i][j] += data[i][k] * other.data[k][j]; } } } return result; } // 矩阵转置 Matrix transpose() const { Matrix result(col, row); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { result.data[j][i] = data[i][j]; } } return result; } // 矩阵求逆 Matrix inverse() const { if (row != col) { throw "非方阵不可求逆!"; } int n = row; Matrix A(*this); Matrix B(n, n); B.eye(); for (int k = 0; k < n; k++) { double max = abs(A.data[k][k]); int index = k; // 找到最大元素所在的行 for (int i = k + 1; i < n; i++) { if (abs(A.data[i][k]) > max) { max = abs(A.data[i][k]); index = i; } } // 如果最大元素为0,则该矩阵不可逆 if (max == 0) { throw "该矩阵不可逆!"; } // 交换第k行和第index行 if (index != k) { for (int j = 0; j < n; j++) { swap(A.data[k][j], A.data[index][j]); swap(B.data[k][j], B.data[index][j]); } } // 使A[k][k]为1 double d = A.data[k][k]; for (int j = 0; j < n; j++) { A.data[k][j] /= d; B.data[k][j] /= d; } // 使A[k][j](j!=k)为0 for (int i = k + 1; i < n; i++) { double d = A.data[i][k]; for (int j = 0; j < n; j++) { A.data[i][j] -= d * A.data[k][j]; B.data[i][j] -= d * B.data[k][j]; } } } // 使A[j][k](j!=k)为0 for (int k = n - 1; k > 0; k--) { for (int i = k - 1; i >= 0; i--) { double d = A.data[i][k]; for (int j = 0; j < n; j++) { A.data[i][j] -= d * A.data[k][j]; B.data[i][j] -= d * B.data[k][j]; } } } return B; } // 单位矩阵 void eye() { if (row != col) { throw "非方阵不可转化为单位矩阵!"; } for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { data[i][j] = (i == j) ? 1 : 0; } } } // 输出矩阵元素 void print() const { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { cout << data[i][j] << "\t"; } cout << endl; } } }; ``` 在这个矩阵中,我们使用了动态二维数组来存储矩阵的数据。在构造函数中,我们使用了resize()函数来动态分配内存。在拷贝构造函数和赋值运算符中,我们直接复制了矩阵的行列数和数据,而不是使用浅拷贝。 在矩阵的按元素加减乘除运算中,我们首先检查了两个矩阵的维度是否匹配,然后按照对应元素相加减乘除的方式计算结果,并返回一个新的矩阵对象。 在矩阵的乘法运算中,我们首先检查了两个矩阵的维度是否匹配,然后按照矩阵乘法的定义计算结果,并返回一个新的矩阵对象。 在矩阵的转置和求逆运算中,我们使用了一些常见的线性代数算法来实现。需要注意的是,在求逆运算中,我们使用了高斯-约旦消元法来求解矩阵的逆矩阵,该算法的时间复杂度为O(n^3)。 最后,我们还实现了一个输出矩阵元素的函数print(),用于调试和测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值