当前位置: 首页 > 编程日记 > 正文

行列式求值、矩阵求逆

#include <iostream>
#include <string>
#include <assert.h>
#include <malloc.h>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
#include <time.h>using namespace std;//动态分配大小位size的一维数组
template<typename T>
bool allocateMemory1D(T **p, const int size)
{*p = NULL;*p = (T *)malloc(size * sizeof(T));if (*p == NULL) return false;return true;
}//动态分配rows行、cols列的二维数组
template<typename T>
bool allocateMemory2D(T ***p, const int rows, const int cols)
{*p = NULL;*p = (T **)malloc(rows * sizeof(T *));if (*p == NULL) return false;memset(*p, 0, sizeof(T *)* rows);for (int i = 0; i < rows; i++){(*p)[i] = (T *)malloc(cols * sizeof(T));if ((*p)[i] == NULL) return false;}return true;
}//释放一维动态数组的空间
template<typename T>
void freeMemory1D(T **p)
{if (*p != NULL){free(*p);*p = NULL;}
}//释放二维动态数组的空间
template<typename T>
void freeMemory2D(T ***p, const int rows)
{if (*p != NULL){for (int i = 0; i < rows; i++){if ((*p)[i] != NULL){free((*p)[i]);(*p)[i] = NULL;}}free(*p);*p = NULL;}
}//template<class T>
//void swap(T &a, T &b)
//{
//	T tmp = a;
//	a = b;
//	b = tmp;
//}//用随机数填充二维数组(矩阵)
template<typename T, typename V>
bool generateNNumbers2D(T **a, int rows, int cols, V minValue, V maxValue)
{//assert(a != NULL && rows > 0 && cols > 0);if (a == NULL || rows < 1 && cols < 1) return false;if (minValue > maxValue) swap(minValue, maxValue);const int N = 999999;srand((unsigned)time(NULL));for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){a[i][j] = rand() % (int)(maxValue - minValue + 1) + minValue + rand() % (N + 1) / (float)(N + 1);}}return true;
}void displayArray2D(double **a, const int rows, const int cols)
{assert(a != NULL && rows > 0 && cols > 0);for (int i = 0; i < rows; i++){printf("%d: ", i + 1);for (int j = 0; j < cols; j++){printf("%lf ", a[i][j]);}printf("\n");}
}//降阶法递归求行列式的值,就是按照线性代数书上的公式,我是按照第一行进行展开
template <typename T>
double static det(T **mat, const int n)
{assert(mat != NULL && n > 0);if (n == 1) return (double)mat[0][0];else if (n == 2) return (double)(mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]);else{int i, j, k, flag = 1, col;double value = 0.0;T **tmpMat = NULL;allocateMemory2D(&tmpMat, n - 1, n - 1);for (i = 0; i < n; i++){for (j = 1; j < n; j++){col = 0;for (k = 0; k < n; k++){if (k != i){tmpMat[j - 1][col++] = mat[j][k];}}}value += mat[0][i] * det(tmpMat, n - 1) * flag;flag = -flag;}freeMemory2D(&tmpMat, n - 1);return value;}
}//将矩阵化为上三角矩阵来求行列式的值,精度比上面的降阶法要低,我没有考虑数据
//溢出的情况,适用范围有限(上面也是)。
double static det1(double **mat, const int n)
{assert(mat && n > 0);const double PRECESION = 1E-6;int row, col, i, j;bool flag = false;int sign = 1;double result = 1.0;for (i = 0; i < n - 1; i++){for (j = i; j < n; j++){if (fabs(mat[i][j]) > PRECESION) break;}if (j >= n){flag = true;break;}if (j != i){//swap rowsfor (col = 0; col < n; col++){result = mat[i][col];mat[i][col] = mat[j][col];mat[j][col] = result;}sign = -sign;}//sub i rowfor (row = j + 1; row < n; row++){double base = mat[row][i] / mat[i][i];for (col = 0; col < n; col++){mat[row][col] -= mat[i][col] * base;}}}if (flag){return 0;}else{result = 1.0;for (i = 0; i < n; i++){result *= mat[i][i];}if (sign < 0){result = -result;}}return result;
}//求一个矩阵的邻接矩阵,T为输入矩阵,adjointMat存放T对应的邻接矩阵,n为矩阵的阶数
template <typename T>
bool adjointMatrix(T **mat, T ** &adjointMat, int n)
{int i, j;if (mat == NULL || n < 1) return false;if (n == 1){adjointMat[0][0] = 1;return true;}T **tmpMat = NULL;allocateMemory2D(&tmpMat, n - 1, n - 1);int sign = -1, row, col, rowIndex, colIndex;for (i = 0; i < n; i++){sign = -sign;int s = sign;for (j = 0; j < n; j++){rowIndex = 0;for (row = 0; row < n; row++){colIndex = 0;if (row != i){for (col = 0; col < n; col++){if (col != j){tmpMat[rowIndex][colIndex] = mat[row][col];colIndex++;}}rowIndex++;}}adjointMat[j][i] = s * det(tmpMat, n - 1);s = -s;}}freeMemory2D(&tmpMat, n - 1);return true;
}//求一个矩阵的逆矩阵
template <typename T>
int inverseMatrix(double d, T **mat, T ** &inverseMat, int n)
{//参数合法性检查if (n < 1 || mat == NULL || inverseMat == NULL) return -2;//double d = det(mat, n);if (fabs(d) < 1E-6) return -1;	//矩阵为奇异矩阵的情况,此时不可逆for (int row = 0; row < n; row++){for (int col = 0; col < n; col++){inverseMat[row][col] = mat[row][col] / d;}}return 0;
}//两个矩阵相乘,mat3 = mat1 * mat2
template <typename T>
bool matrixMultiply(T **mat1, T **mat2, T **&mat3, int n)
{if (mat1 == NULL || mat2 == NULL || n < 1) return false;for (int row = 0; row < n; row++){for (int col = 0; col < n; col++){double sum = 0.0;for (int k = 0; k < n; k++){sum += mat1[row][k] * mat2[k][col];}mat3[row][col] = sum;}}return true;
}//误差分析
template <typename T>
bool compareMatrix(T **referenceMat, T **mat, int n, double *absoluteError, double *relativeError)
{if (referenceMat == NULL || mat == NULL || n < 1 || absoluteError == NULL || relativeError == NULL) return false;*absoluteError = 0;*relativeError = 0;for (int row = 0; row < n; row++){for (int col = 0; col < n; col++){double tmp = fabs(mat[row][col] - referenceMat[row][col]);*absoluteError += tmp;if (fabs(referenceMat[row][col]) > 1E-6) *relativeError += tmp / referenceMat[row][col];}}return true;
}void main(void)
{int n, i, j, ret;double **mat = NULL;double **adjointMat = NULL;double absouluteError, relativeError, d;double **tmpMat = NULL;bool isReversible;bool isDataAutoGenerate;char ch;char buf[256];cout << "自动生成矩阵吗(y/Y:是):";cin >> ch;isDataAutoGenerate = (ch == 'y' || ch == 'Y');cin.getline(buf, sizeof(buf));	//清空输入缓冲区cout << "输入行列式的阶数:";while (cin >> n){allocateMemory2D(&mat, n, n);if (isDataAutoGenerate){generateNNumbers2D(mat, n, n, -100, 100);cout << "自动生成的" << n << "阶矩阵为:" << endl;displayArray2D(mat, n, n);}else{cout << "依次输入矩阵的每一个元素:\n";for (i = 0; i < n * n; i++) cin >> mat[i / n][i % n];}cout << "分别用两种方法计算行列式的值."<<endl;d = det(mat, n);cout << "1.行列式的值为:" << d << endl;cout << "2.行列式的值为:" << det1(mat, n) << endl;allocateMemory2D(&adjointMat, n, n);cout<<"伴随矩阵为:"<<endl;if (!adjointMatrix(mat, adjointMat, n)) cout<<"伴随矩阵求解失败!"<<endl;else{for (i = 0; i < n; i++){for (j = 0; j < n; j++){cout<<adjointMat[i][j]<<" ";}cout<<endl;}}ret = inverseMatrix(d, adjointMat, adjointMat, n);if (ret == -2) {isReversible = false;cout << "参数错误" << endl;}else if (ret == -1){isReversible = false;cout << "矩阵不可逆" << endl;}else{isReversible = true;cout << "逆矩阵:" << endl;for (i = 0; i < n; i++){for (j = 0; j < n; j++){cout<<adjointMat[i][j]<<" ";}cout<<endl;}}if (isReversible){cout << "计算一个矩阵与其对应的逆矩阵的乘积:" << endl;allocateMemory2D(&tmpMat, n, n);ret = matrixMultiply(mat, adjointMat, tmpMat, n);for (i = 0; i < n; i++){for (j = 0; j < n; j++){cout << tmpMat[i][j] << " ";}cout << endl;}}//将mat矩阵置为单位矩阵for (i = 0; i < n; i++){for (j = 0; j < n; j++){if (i == j){mat[i][j] = 1;}else mat[i][j] = 0;}}if (isReversible){cout << "原矩阵 * 逆矩阵 和 原矩阵同规模的单位矩阵作对比,看误差多大." << endl;compareMatrix(mat, tmpMat, n, &absouluteError, &relativeError);cout << "绝对误差:" << absouluteError << endl;cout << "相对误差:" << relativeError << endl;}freeMemory2D(&mat, n);freeMemory2D(&adjointMat, n);freeMemory2D(&tmpMat, n);cout << "输入行列式的阶数:";}
}

相关文章:

IP 地址子网划分

1.你所选择的子网掩码将会产生多少个子网2的x次方-2(x代表网络位借用主机的位数&#xff0c;即2进制为1的部分&#xff0c;现在的网络中&#xff0c;已经不需要-2&#xff0c;已经可以全部使用&#xff0c;不过需要加上相应的配置命令&#xff0c;例如CISCO路由器需要加上ip su…

git rebase 和 git merger

& git merge 在上图中&#xff0c;每一个绿框均代表一个commit。除了c1&#xff0c;每一个commit都有一条有向边指向它在当前branch当中的上一个commit。 图中的项目&#xff0c;在c2之后就开了另外一个branch&#xff0c;名为experiment。在此之后&#xff0c;master下的修…

matplotlib绘制三维轨迹图

1. 绘制基本三维曲线 # import necessary module from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt import numpy as np# load data from file # you can replace this using with open data1 np.loadtxt("./pos.txt") # print (data1) n…

求一个矩阵的最大子矩阵

#include <iostream> #include <string> #include <assert.h> #include <malloc.h> #include <iostream> #include <stdlib.h> #include <memory.h> #include <time.h> #include <limits.h>using namespace std;//动态分…

tcpdump抓包文件提取http附加资源

2019独角兽企业重金招聘Python工程师标准>>> 前面几篇文章铺垫了一大批的协议讲解&#xff0c;主要是为了提取pcap文件中http协议附加的资源。 1、解析pcap文件&#xff0c;分为文件格式头&#xff0c;后面就是数据包头和包数据了 2、分析每个包数据&#xff0c;数据…

smobiler介绍(二)

类似开发WinForm的方式&#xff0c;使用C#开发Android和IOS的移动应用&#xff1f;听起来感觉不可思议&#xff0c;那么Smobiler平台到底是如何实现的呢&#xff0c;这里给大家介绍一下。客户端Smobiler分为两种客户端&#xff0c;一种是开发版&#xff0c;一种是打包版开发版&…

Matplotlib基本用法

Matplotlib Matplotlib 是Python中类似 MATLAB 的绘图工具&#xff0c;熟悉 MATLAB 也可以很快的上手 Matplotlib。 1. 认识Matploblib 1.1 Figure 在任何绘图之前&#xff0c;我们需要一个Figure对象&#xff0c;可以理解成我们需要一张画板才能开始绘图。 import matplot…

HDU1201 18岁生日【日期计算】

18岁生日 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 32851 Accepted Submission(s): 10649Problem DescriptionGardon的18岁生日就要到了&#xff0c;他当然很开心&#xff0c;可是他突然想到一个问题&am…

TypeScript 从听说到入门(上篇)

我为什么会这样念念又不忘 / 你用什么牌的箭刺穿我心脏 我也久经沙场 / 戎马生涯 / 依然 / 被一箭刺伤 ——李荣浩《念念又不忘》 接下来我会分上、下两篇文章介绍 TypeScript。 我也是 TypeScript 初学者&#xff0c;这两篇文章是我的学习笔记&#xff0c;来源于一个系列的免费…

SLAM前端中的视觉里程计和回环检测

1. 通常的惯例是把 VSLAM 分为前端和后端。前端为视觉里程计和回环检测&#xff0c;相当于是对图像数据进行关联&#xff1b;后端是对前端输出的结果进行优化&#xff0c;利用滤波或非线性优化理论&#xff0c;得到最优的位姿估计和全局一致性地图。 1 前端&#xff1a;图像数…

粗心导致的bug

不管是调试程序还是直接看输出i都为2&#xff0c;下面是运行时输出的&#xff1a; 用vs2010以前遇到更奇葩的事&#xff0c;这次用vs2013也是遇到奇葩&#xff0c;taskNumber值为2一定&#xff0c;下面两个循环体&#xff0c;每个循环体各执行一次&#xff0c;程序输出i 2真是…

gearman中任务的优先级和返回状态

gearman中任务的优先级和返回状态 一、任务的优先级 同步阻塞调用&#xff0c;等待返回结果 doLow:最低优先 doNomal:正常优先级 doHigh:最优先执行 异步派发任务&#xff0c;不等待返回结果&#xff0c;返回任务句柄&#xff0c;通过该句柄可获取任务运行状态信息 doLowBackgr…

VMware学习使用笔记

本人在学习基础上&#xff0c;结合实际项目实现总结的笔记。以下内容都是基于VMware vSphere 6.7的官方文档中vSAN的规划和部署而来&#xff0c;网址https://docs.vmware.com/cn/VMware-vSphere/index.html。 对于ESXi系统 对于内存不足512G&#xff0c;可以从USB或Micro SD引导…

【原】Java学习笔记020 - 面向对象

1 package cn.temptation;2 3 public class Sample01 {4 public static void main(String[] args) {5 // 成员方法的参数列表&#xff1a;6 // 1、参数列表中的数据类型是值类型7 // 2、参数列表中的数据类型是引用类型8 // A&#xff1a;…

win32 wmi编程获取系统信息

//GetSysInfo.h#pragma once#include <afxtempl.h>class GetSysInfo { public:GetSysInfo(void);~GetSysInfo(void);public: /********获取操作系统版本&#xff0c;Service pack版本、系统类型************/ void GetOSVersion(CString &strOSVersion,CString &…

cmake 注意事项

1. add_subdirectory()调用 CMake将在每次add_subdirectory()调用时创建一个新的变量作用域,因此这个参数最好的用法是放在cmaklists的最后使用&#xff0c;这样的话创建的新的变量的作用范围与内存的变化就不会影响到后面的变量的使用。 查看并打印在cmake里面定义的宏在&am…

Jmeter 使用自定义变量

有些情况下比如发起测试时URL的主机名和端口需要在采样器中出现多次&#xff0c;这样就有个问题&#xff0c;当测试的主机更改时&#xff0c; 我们需要修改主机名称&#xff0c;这时就需要修改多个地方&#xff0c;如果多的情况会有遗漏。如果我们在配置脚本的时候&#xff0c;…

Kubernetes1.5源码分析(二) apiServer之资源注册

源码版本 Kubernetes v1.5.0 简介 k8s里面有各种资源&#xff0c;如Pod、Service、RC、namespaces等资源&#xff0c;用户操作的其实也就是这一大堆资源。但这些资源并不是杂乱无章的&#xff0c;使用了GroupVersion的方式组织在一起。每一种资源都属于一个Group&#xff0c;而…

opencv3 视频稳像

OpneCV3.x中提供了专门应用于视频稳像技术的模块&#xff0c;该模块包含一系列用于全局运动图像估计的函数和类。结构体videostab::RansacParams实现了RANSAC算法&#xff0c;这个算法用来实现连续帧间的运动估计。videostab::MotionEstimatorBase是基类中所有全局运动估计方法…

perf+火焰图 = 性能分析利器

perf 1. perf安装 sudo apt install linux-tools-common检查是否安装好 perf如果出现 You may need to install the following packages for this specific kernel:推荐安装可以按照提示将推荐安装包全部安装好 sudo apt-get install linux-tools-对应版本-generic linux-c…

3- MySQL数据类型

MySQL表字段类型 MySQL数据表的表示一个二维表&#xff0c;由一个或多个数据列构成。 每个数据列都有它的特定类型&#xff0c;该类型决定了MySQL如何看待该列数据&#xff0c;并且约束列存放相应类型的数据。 MySQL中的列表有三种&#xff1a;数值类&#xff0c;字符串类和日期…

AddressSanitizer+cmake

1. AddressSanitizercmake(Linux) 编译指令&#xff1a; CXXFLAGS通常需要加上 -fsanitizeaddress -fno-omit-frame-pointer #打印函数调用路径 -fsanitize-recoveraddress #AddressSanitizer遇到错误时能够继续-fsanitizeaddress-fno-omit-frame-pointer-fsanitize-rec…

vibe前景提取改进算法

// improveVibeAlgorithm.h #ifndef IMPROVED_VIBE_ALGORITHM_H #define IMPROVED_VIBE_ALGORITHM_H#include <opencv2/opencv.hpp> using namespace std;#define WINSIZE 5 // Vibe改进算法, Barnich, Olivier & Droogenbroeck, Marc. (2009). // ViBE: A powerfu…

npm-debug.log文件出现原因

项目主目录下总是会出现这个文件&#xff0c;而且不止一个&#xff0c;原因是npm i 的时候&#xff0c;如果报错&#xff0c;就会增加一个此文件来显示报错信息&#xff0c;npm install的时候则不会出现。转载于:https://www.cnblogs.com/liuna/p/6558006.html

AutoFac Ioc依赖注入容器

本文原著&#xff1a;牛毅 原文路径 http://niuyi.github.io/blog/2012/04/06/autofac-by-unit-test/ 理解IOC容器请看下图&#xff1a; 没有使用IOC容器的情况下: 使用IOC容器的情况下&#xff1a; 去掉IOC容器的情况后&#xff1a; IOC容器又像一个插座&#xff0c;将电输送…

Linux安装App记录

Ubuntu18.04安装微信

windows socket编程入门示例3

// Lock.h #ifndef _Lock_H #define _Lock_H #include <windows.h>class CriticalSection { private:CRITICAL_SECTION g_cs; //临界区 public:CriticalSection();~CriticalSection();void Lock();void UnLock(); }; #endif// Lock.cpp #include "Lock.h"…

游戏开发:js实现简单的板球游戏

js实现简单的板球游戏大家好&#xff0c;本次我们来使用js来实现一个简单的板球游戏。截图如下&#xff1a;首先&#xff0c;设计页面代码&#xff0c;页面代码很简单&#xff0c;因为整个几乎是使用js编写的&#xff0c;页面几乎没有代码&#xff0c;如下&#xff1a;<!DOC…

SLAM精度测评——EVO进阶

1. 基本概念 1.1 Umeyama算法 ATE&#xff1a; evo_ape tum state_groundtruth_estimate0/data.tum orb2/CameraTrajectory.txt -r trans_part -va --plot --plot_mode xy --save_results /home/sun/evo/v1_01_easy/orb2/ate.zip RPE&#xff1a; evo_rpe tum state_groun…

python读取图片并且显示

使用python-opencv读取图片&#xff0c;利用opencv或matplotlib显示图片。 # -*- coding: utf-8 -*-import numpy as np from matplotlib import pyplot as plt #import urllib import cv2def load_image1(file):# Load an color image in grayscaleimg cv2.imread(file,0)cv…