[C++] 计算行列式的若干种方法

测试样例

10
1 3 4 0 2 0 4 -5 9 3
6 7 8 5 2 7 8 4 6 2
8 7 6 9 8 7 6 8 45 2
4 3 2 5 4 3 2 8 6 4
1 2 0 4 1 2 3 9 87 6
5 6 7 8 5 6 8 6 8 1
9 8 7 6 9 8 7 -9 2 3
5 6 3 5 4 1 8 7 9 2
-9 8 6 2 4 56 6 3 8 9
5 3 6 8 6 6 1 8 2 3
答案:7583304

按行(列)展开法

#include <iostream>
#include <fstream>
using namespace std;
//构造第一行第line个元素的余子式
void StructMinor(double* matrix, int dimension, int line, double* minor){
	int ptr=0;
	for(int cnt1=1; cnt1<dimension; cnt1++) for(int cnt2=0; cnt2<dimension; cnt2++)
		if(line!=cnt2) minor[ptr++] = matrix[cnt1*dimension+cnt2];
	return;
}
double Determinant(double* matrix, int dimension){
	//递归基,当矩阵中只有一个元素的时候,行列式的值即为实数值
	if(dimension <= 1) return *matrix;
	double minor[(dimension-1)*(dimension-1)];
	double determinant = 0;
	int sign = 1;
	for(int cnt=0; cnt<dimension; cnt++){
		//构造matrix[0][cnt]的余子式
		StructMinor(matrix, dimension, cnt, minor);
		//determinant=ΣELEMENT0j*A0j
		determinant += sign*matrix[cnt]*Determinant(minor, dimension-1);
		sign *= -1;
	}
	return determinant;
}
int main(){
	int dimension;
	int scale;
	double matrix[100];
	ifstream input("matrix.txt");
	input >> dimension;
	scale = dimension*dimension;
	for(int cnt=0; cnt<scale; cnt++) input >> matrix[cnt];
	cout << Determinant(matrix, dimension);
	return 0;
}

计算结果

在这里插入图片描述

高斯消元转化为上三角阵

#include <iostream>
#include <fstream>
using namespace std;
//通过高斯消元法化矩阵为upper triangle matrix
void GaussElimination2UTM(double* matrix, int dimension){
	//注意cnt3一定要从矩阵最右侧运算至左侧,否则主元列对应元素归零,运算就无法正常进行
	for(int cnt1=0; cnt1<dimension; cnt1++) for(int cnt2=cnt1+1; cnt2<dimension; cnt2++) for(int cnt3=dimension-1; cnt3>=cnt1; cnt3--)
		matrix[cnt2*dimension+cnt3] += -1*matrix[cnt1*dimension+cnt3]*matrix[cnt2*dimension+cnt1]/matrix[cnt1*dimension+cnt1];
	return;
}
double Determinant(double* matrix, int dimension){
	double determinant=1;
	GaussElimination2UTM(matrix, dimension);
	//上三角阵对角线乘积即为行列式
	for(int cnt=0; cnt<dimension; cnt++) determinant *= matrix[cnt*dimension+cnt];
	return determinant;
}
int main(){
	int dimension;
	int scale;
	double matrix[100];
	ifstream input("matrix.txt");
	input >> dimension;
	scale = dimension*dimension;
	for(int cnt=0; cnt<scale; cnt++) input >> matrix[cnt];
	cout << Determinant(matrix, dimension) << '\n';
	return 0;
}

计算结果

在这里插入图片描述
计算结果出现明显错误,原因是这个矩阵在进行行变换的时候出现了第四行第四列,极小的主元,所以根本原因在于double的精度对于这种算法依然不够

对于测试样例
7
1 3 4 0 2 33 4
6 7 8 5 62 7 8
98 7 6 9 8 7 6
54 3 2 5 4 3 2
1 2 0 4 1 2 34
5 6 7 8 5 6 78
9 8 7 6 9 8 72
在这里插入图片描述
可以得出正确结果
尽管这种算法对精度要求很高,但是计算速度很快

定义法

使用行列式的定义式进行计算

代码

#include <iostream>
#include <fstream>
using namespace std;
int dimension;
char permutation[10];
double matrix[100];
double Determinant(int depth, double sign){
	double result;
	//递归基,在递归树的叶子返回定义的求和式的其中一项
	if(depth>=dimension){
		result = sign;
		for(int cnt=0; cnt<dimension; cnt++) result *= matrix[cnt*dimension+permutation[cnt]];
	}
	else{
		int temp;
		//不交换的情况,对逆序数无贡献
		result = Determinant(depth+1, sign);
		//将后续几个元素分别于第一个元素进行交换,逆序数加一
		for(int cnt=depth+1; cnt<dimension; cnt++){
			//交换
			temp = permutation[depth];
			permutation[depth] = permutation[cnt];
			permutation[cnt] = temp;
			//计算此情况下所有值之和
			result += Determinant(depth+1, -1*sign);
			//换回
			temp = permutation[depth];
			permutation[depth] = permutation[cnt];
			permutation[cnt] = temp;
		}
	}
	return result;
}
int main(){
	int scale;
	ifstream input("matrix.txt");
	input >> dimension;
	for(int cnt=0; cnt<dimension; cnt++) permutation[cnt] = cnt;
	scale = dimension*dimension;
	for(int cnt=0; cnt<scale; cnt++) input >> matrix[cnt];
	cout << Determinant(0,1) << '\n';
	return 0;
}

测试结果

在这里插入图片描述

有问题欢迎提出

发布了2 篇原创文章 · 获赞 1 · 访问量 1144

猜你喜欢

转载自blog.csdn.net/TZR986981442/article/details/104441144