矩阵求逆c++实现

高斯消元法可以用来找出一个可逆矩阵的逆矩阵。设A 为一个N * N的矩阵,其逆矩阵可被两个分块矩阵表示出来。将一个N * N单位矩阵 放在A 的右手边,形成一个N * 2N的分块矩阵B = [A,I]
。经过高斯消元法的计算程序后,矩阵B 的左手边会变成一个单位矩阵I ,而逆矩阵A ^(-1) 会出现在B 的右手边。假如高斯消元法不能将A 化为三角形的格式,那就代表A 是一个不可逆的矩阵。应用上,高斯消元法极少被用来求出逆矩阵。高斯消元法通常只为线性方程组求解。

 //********************************
//*** 求任何一个实矩阵的逆***
//********************************
#include "stdafx.h"
#include <math.h>
#include <malloc.h>
#include <iostream>
#include <iomanip>
using namespace std;
#define  N  10                //定义方阵的最大阶数为10
//函数的声明部分
float MatDet(float *p, int n);                    //求矩阵的行列式
float Creat_M(float *p, int m, int n, int k);    //求矩阵元素A(m, n)的代数余之式
void print(float *p, int n);                    //输出矩阵n*n
bool Gauss(float A[][N], float B[][N], int n);    //采用部分主元的高斯消去法求方阵A的逆矩阵B
int main()
{
    float *buffer, *p;            //定义数组首地址指针变量
    int row, num;                //定义矩阵的行数和矩阵元素个数
    int i, j;
    float determ;                //定义矩阵的行列式
    float a[N][N], b[N][N];
    int n;
    cout << "采用逆矩阵的定义法求矩阵的逆矩阵!\n";
    cout << "请输入矩阵的行数: ";
    cin >> row;
    num = 2 * row * row;
    buffer = (float *)calloc(num, sizeof(float));        //分配内存单元
    p = buffer;
    if (NULL != p)
    {
        for (i = 0; i < row; i++)
        {
            cout << "Please input the number of " << i+1 << " row: ";
            for (j = 0; j < row; j++)
            {
                cin >> *p++;
            }
        }
    }
    else
    {
        cout << "Can‘t distribute memory\n";
    }
    cout << "The original matrix : \n";
    print(buffer, row);                //打印该矩阵

    determ = MatDet(buffer, row);    //求整个矩阵的行列式
    p = buffer + row * row;
    if (determ != 0)
    {
        cout << "The determinant of the matrix is " << determ << endl;
        for (i = 0; i < row; i++)    //求逆矩阵
        {
            for (j = 0; j < row; j++)
            {
                *(p+j*row+i) = Creat_M(buffer, i, j, row)/determ;
            }
        }
        cout << "The inverse matrix is: " << endl;
        print(p, row);                //打印该矩阵
    }
    else
    {
        cout << "The determinant is 0, and there is no inverse matrix!\n";
    }
    free(buffer);        //释放内存空间
    cout << "采用部分主元的高斯消去法求方阵的逆矩阵!\n";
    cout << "请输入方阵的阶数: ";
    cin >> n;
    cout << "请输入" << n << "阶方阵: \n";
    //输入一个n阶方阵
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            cin >> a[i][j];
        }
    }
    //运用高斯消去法求该矩阵的逆矩阵并输出
    if (Gauss(a, b, n))
    {
        cout << "该方阵的逆矩阵为: \n";
        for (i = 0; i < n; i++)
        {
            cout << setw(4);
            for (j = 0; j < n; j++)
            {
                cout << b[i][j] << setw(10);
            }
            cout << endl;
        }
    }
	getchar();
    return 0;
}
//-----------------------------------------------
//功能: 求矩阵(n*n)的行列式
//入口参数: 矩阵的首地址,矩阵的行数
//返回值: 矩阵的行列式值
//----------------------------------------------
float MatDet(float *p, int n)
{
    int r, c, m;
    int lop = 0;
    float result = 0;
    float mid = 1;
    if (n != 1)
    {
        lop = (n == 2) ? 1 : n;            //控制求和循环次数,若为2阶,则循环1次,否则为n次
        for (m = 0; m < lop; m++)
        {
            mid = 1;            //顺序求和, 主对角线元素相乘之和
            for (r = 0, c = m; r < n; r++, c++)
            {
                mid = mid * (*(p+r*n+c%n));
            }
            result += mid;
        }
        for (m = 0; m < lop; m++)
        {
            mid = 1;            //逆序相减, 减去次对角线元素乘积
            for (r = 0, c = n-1-m+n; r < n; r++, c--)
            {
                mid = mid * (*(p+r*n+c%n));
            }
            result -= mid;
        }
    }
    else
        result = *p;
    return result;
}
//----------------------------------------------------------------------------
//功能: 求k*k矩阵中元素A(m, n)的代数余之式
//入口参数: k*k矩阵的首地址,矩阵元素A的下标m,n,矩阵行数k
//返回值: k*k矩阵中元素A(m, n)的代数余之式
//----------------------------------------------------------------------------
float Creat_M(float *p, int m, int n, int k)
{
    int len;
    int i, j;
    float mid_result = 0;
    int sign = 1;
    float *p_creat, *p_mid;
    len = (k-1)*(k-1);            //k阶矩阵的代数余之式为k-1阶矩阵
    p_creat = (float*)calloc(len, sizeof(float)); //分配内存单元
    p_mid = p_creat;
    for (i = 0; i < k; i++)
    {
        for (j = 0; j < k; j++)
        {
            if (i != m && j != n) //将除第i行和第j列外的所有元素存储到以p_mid为首地址的内存单元
            {
                *p_mid++ = *(p+i*k+j);
            }
        }
    }
    sign = (m+n)%2 == 0 ? 1 : -1;    //代数余之式前面的正、负号
    mid_result = (float)sign*MatDet(p_creat, k-1);
    free(p_creat);
    return mid_result;
}
//-----------------------------------------------------
//功能: 打印n*n矩阵
//入口参数: n*n矩阵的首地址,矩阵的行数n
//返回值: 无返回值
//-----------------------------------------------------
void print(float *p, int n)
{
    int i, j;
    for (i = 0; i < n; i++)
    {
        cout << setw(4);
        for (j = 0; j < n; j++)
        {
            cout << setiosflags(ios::right) << *p++ << setw(10);
        }
        cout << endl;
    }
}
//------------------------------------------------------------------
//功能: 采用部分主元的高斯消去法求方阵A的逆矩阵B
//入口参数: 输入方阵,输出方阵,方阵阶数
//返回值: true or false
//-------------------------------------------------------------------
bool Gauss(float A[][N], float B[][N], int n)
{
    int i, j, k;
    float max, temp;
    float t[N][N];                //临时矩阵
    //将A矩阵存放在临时矩阵t[n][n]中
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            t[i][j] = A[i][j];
        }
    }
    //初始化B矩阵为单位阵
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            B[i][j] = (i == j) ? (float)1 : 0;
        }
    }
    for (i = 0; i < n; i++)
    {
        //寻找主元
        max = t[i][i];
        k = i;
        for (j = i+1; j < n; j++)
        {
            if (fabs(t[j][i]) > fabs(max))
            {
                max = t[j][i];
                k = j;
            }
        }
        //如果主元所在行不是第i行,进行行交换
        if (k != i)
        {
            for (j = 0; j < n; j++)
            {
                temp = t[i][j];
                t[i][j] = t[k][j];
                t[k][j] = temp;
                //B伴随交换
                temp = B[i][j];
                B[i][j] = B[k][j];
                B[k][j] = temp;
            }
        }
        //判断主元是否为0, 若是, 则矩阵A不是满秩矩阵,不存在逆矩阵
        if (t[i][i] == 0)
        {
            cout << "There is no inverse matrix!";
            return false;
        }
        //消去A的第i列除去i行以外的各行元素
        temp = t[i][i];
        for (j = 0; j < n; j++)
        {
            t[i][j] = t[i][j] / temp;        //主对角线上的元素变为1
            B[i][j] = B[i][j] / temp;        //伴随计算
        }
        for (j = 0; j < n; j++)        //第0行->第n行
        {
            if (j != i)                //不是第i行
            {
                temp = t[j][i];
                for (k = 0; k < n; k++)        //第j行元素 - i行元素*j列i行元素
                {
                    t[j][k] = t[j][k] - t[i][k]*temp;
                    B[j][k] = B[j][k] - B[i][k]*temp;
                }
            }
        }
    }
	getchar();
    return true;
}

实验结果:

矩阵求逆c++实现,布布扣,bubuko.com

时间: 2024-10-12 03:28:05

矩阵求逆c++实现的相关文章

由正交矩阵构建的仿射变换矩阵求逆的快速算法

原文地址http://blog.csdn.net/i_dovelemon/article/details/45827953 齐次坐标 我们都知道,在3D图形学中,所有的变换都可以划分为三种最基础的变换方式,分别为: 旋转变换 缩放变换 平移变换 通过对这三种变换进行组合,就能够实现任意的变换形式. 在3D坐标下,如果向量使用3D向量表示的话,对于这三种变换的处理方式如下: 旋转变换:乘法运算 缩放变换:乘法运算 平移变换:加法运算 也就是说,这三种变换的处理方式是不同的,旋转和缩放变换能够通过乘

矩阵求逆算法及程序实现(C++)

在做课题时,遇到了求多项式问题,利用了求逆方法.矩阵求逆一般使用简单的算法,还有快速算法 如全选主元高斯-约旦消元法,但本文程序主要写了简单的矩阵求逆算法定义法之伴随矩阵求逆公式如下,其中A可逆: ,其中是的伴随矩阵.. 1.给定一个方阵,非奇异(不是也可,程序有考虑): 2.由矩阵得到其行列式,求其值如|A|: 3.求其伴随矩阵: 4.得到其逆矩阵. 主要函数如下: 1 //得到给定矩阵src的逆矩阵保存到des中. 2 bool GetMatrixInverse(double src[N][

【题解】Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4128 大水题一道 使用大步小步算法,把数字的运算换成矩阵的运算就好了 矩阵求逆?这么基础的线代算法我也不想多说,还是自行百度吧 需要注意的是矩阵没有交换律,所以在计算$B\cdot A^{-m}$的时候不要把顺序搞混 代码: 1 #include <cstring> 2 #include <cstdio> 3 #include <algorithm> 4 #inc

自适应滤波:矩阵求逆

作者:桂. 时间:2017-04-02  10:36:09 链接:http://www.cnblogs.com/xingshansi/p/6658655.html 声明:欢迎被转载,不过记得注明出处哦~  [读书笔记09] 前言 西蒙.赫金的<自适应滤波器原理>第四版第八章:最小二乘法.因为最小二乘涉及到矩阵求逆,因为通常对于秩缺矩阵其逆是不可求的,这就需要借助广义逆矩阵.而广义逆矩阵可以借助奇异值分解(SVD,Singularly Valuable Decomposition)进行求解. 有

lapack笔记:矩阵求逆

在有限元等参单元计算中,大量用到Jacobi矩阵的求逆. 这里给出一个使用lapack库函数求2x2矩阵逆的例子: /********************************************************** File: test_lapack.c Author: Liang Zheng E-mail: [email protected] Date: 2014-6-19 **************************************************

矩阵求逆(二):逆矩阵

1.数学定义   定义:对于n阶矩阵A,如果有一个n阶矩阵B,使 AB=BA=E 则说矩阵A是可逆的,并把矩阵B称为A的逆矩阵. 定理:若矩阵A可逆,则|A|≠0. 定理:若|A|≠0,则矩阵A可逆,且 A-1=1/|A|*A* 2.算法实现 1)矩阵的行列式 ''' <summary> ''' 返回一个矩阵的行列式 ''' </summary> ''' <param name="dMatrix">原矩阵</param> ''' <

图像处理之基础---矩阵求逆实现

最近做一个加密算法遇到需要计算矩阵的逆,闲着无聊,记录一下,以后免得再麻烦. [cpp] view plaincopyprint? #include #include #include #define MAX 20 #define E 0.000000001 /** * 计算矩阵src的模 */ double calculate_A( double src[][MAX], int n ) { int i,j,k,x,y; double tmp[MAX][MAX], t; double resul

BZOJ 4128 Matrix BSGS+矩阵求逆

题意:链接 方法: BSGS+矩阵求逆 解析: 这题就是把Ax=B(mod C)的A和B换成了矩阵. 然而别的地方并没有改动. 所以就涉及到矩阵的逆元这个问题. 矩阵的逆元怎么求呢? 先在原矩阵后接一个单位矩阵,不妨设右对角线 先把原矩阵进行高斯消元 且消成严格右对角线的单位矩阵的形式. 然后在消元的同时把单位矩阵的部分一并计算,最后单位矩阵就变成了它的逆矩阵. 这道题保证矩阵有逆 然而没有逆矩阵的情况就是高斯消元搞不成. 所以判断应该也好判断. 另外,刚刚实测本题数据,关于将矩阵的hash,直

C++实现矩阵求逆

最近实现一个算法要用到求逆等矩阵运算,在网上搜到一个别人写的矩阵类,试了一下效果不错,贴在这里,做个保存. matrix.h文件: 1 #ifndef __MATRIX_H__ 2 #define __MATRIX_H__ 3 4 #pragma once 5 6 #include <iostream> 7 #include <fstream> 8 #include <sstream> 9 #include <vector> 10 #include <