求矩阵行列式以及其他一些东西

嘛。。因为一道水题做不出来而被大佬鄙视的我决定让计算机来做(我不信大佬还能够有计算机快2333
稍微写了点代码实现了求行列式的功能。如果有时间的话说不定会把求逆也给码了(咕咕咕

#include<iostream>
#include<stdlib.h>
using namespace std;
void input(double *a,int n,int m){//输入n行m列的a 
	cout<<"请输入一个"<<n<<"*"<<m<<"的矩阵\n"; 
	for (int i=0;i<n;i++)
	for (int j=0;j<m;j++)cin>>a[i*n+j];
} 
void print(double *a,int n,int m){//打印矩阵 
	for (int i=0;i<n;i++){
	for (int j=0;j<m;j++)cout<<a[i*m+j]<<" ";
	cout<<endl;
	}
	return ;
}
double det(double*,int);//声明行列式函数 
void det_use();
main (){
	int choose ;
	while (1){
	printf("请输入一个数字\n0.退出程序\n1.计算行列式\n2.求矩阵的逆");
	cin>>choose;
	if (choose==1)cheng();
	else if (choose==0){cout<<"感谢使用";break;}	
	else if (choose==1)det_use();
	else if (choose==2)contrary_use();
	}
	return 0;
}
void divide_Matrix(double *a,double*b,double p,int n){//将n列的a行乘p减到第b行
for (int i=0;i<n;i++)
b[i]-=a[i]*p;
return ;
}
void swap_Matrix(double **a,double **b){//对矩阵做列变换 
	double *tmp;
	tmp=*a;
	*a=*b;
	*b=tmp;
	return;
} //这里曾犯了一个错误,定义了double**tmp,然后进行运算,即野指针然后gg了 
void clean_Matrix(double **p,int i,int n){//p[i]指向的是第i行 ,将第i+1到第n行的第i列全部变成0 
	for (int j=i+1;j<n;j++){
		divide_Matrix(p[i],p[j],p[j][i]/p[i][i],n);
	}
	return;
} 
double det(double*a,int n){//用高斯消元法化为上三角行列式求值
double **p=(double**)malloc(sizeof(double*)*n);
for (int i=0;i<n;i++)p[i]=a+i*n;//将p[i][j]与之对应 
//先对第一列进行
int sgn=1,i=0,j=0;
bool c;
for (i=0;i<n;i++){
	c=0;
	for (j=i;j<n;j++){//从第i行开始找 
		if (p[j][i])//若第j行i列不为0,那么就可以把第j行和第i行换个位置
		{
			c=1;//需要判定有没有一个非0的数如果没有应该返回0 
			if(j==i) //在这里我需要将其之下的所有第i列的减掉所以我们编写一个函数来完成这一件事 
			{clean_Matrix(p,i,n);break;}
			else if (j>i){
				swap_Matrix(&p[i],&p[j]);
				sgn*=-1;
				clean_Matrix(p,i,n);
				break;
			}
		}
	}
//	for (int i=0;i<n;i++)print(p[i],1,n),cout<<endl;
	if (!c)return 0;
}
double deta=1;
for (int i=0;i<n;i++)deta*=p[i][i];
deta*=sgn;
return deta;
}
void det_use(){
	int n;
	cout<<"请输入矩阵的阶数\n";
	cin>>n;
	double *p=(double*)malloc(sizeof(double)*n*n);
	cout<<"请输入矩阵的项\n";
	for (int i=0;i<n;i++)
	for (int j=0;j<n;j++)cin>>p[i*n+j];
	cout<<"此矩阵的行列式的值为:\n";
	cout<<det(p,n)<<endl;
	return; 
} 

之后因为闲的蛋疼就又把求矩阵的逆的代码给写出来了,用的仍然是高斯消元法
下面是核心算法

void contrary(double **p,double **I,int n){//p,I是指向行的指针所以 p[i][j]指的是第i行j列的元素 ,p是所输入的矩阵I是单位矩阵 
	for (int i=0;i<n;i++)//仍然是从列开始考虑
	{
		for (int j=i;j<n;j++){
			if (p[i][j]){
				if (i!=j){
					double*tmp;
					tmp=p[i];
					p[i]=p[j];
					p[j]=tmp;
					tmp=I[i];
					I[i]=I[j];
					I[j]=tmp; 
				}
				for (int k=i+1;k<n;k++){
				divide_Matrix(I[i],I[k],p[k][i]/p[i][i],n);
				divide_Matrix(p[i],p[k],p[k][i]/p[i][i],n);
//			print(*p,n,n);cout<<endl;print(*I,n,n);cout<<endl;
				}
			}
			else if (p[i][j]==0)continue;
			break;
		}
	 }//此时p应该已经被变换成上三角矩阵,我们考虑将其继续消元 ,为此我们设置一个对列进行操作的函数(这里错了,又进行行变换又进行列变换其实是即左乘又右乘,不能得到答案 
	  for (int i=n-1;i>=0;i--){
	  	for (int j=i-1;j>=0;--j){
	  	divide_Matrix(I[i],I[j],p[j][i]/p[i][i],n);
	  	divide_Matrix(p[i],p[j],p[j][i]/p[i][i],n);
//	  	print(*p,n,n),cout<<endl;print(*I,n,n);cout<<endl;
		  }
	  }//这时候p就应该已经是一个对角矩阵
	  //现在来处理对角矩阵的情况
	   for (int i=0;i<n;i++)multply_Matrix_line(I[i],p[i][i],n),multply_Matrix_line(p[i],p[i][i],n);
	   return; 
}

其中divide_Matrix(doublea,doubleb,double p,int n)是一个作用为把a指向的n个元素乘p减到b指向的n个元素。
不过在运行这个程序之前需要判断其行列式为不为0;
这个用上面的det函数即可说明

void contrary_use(){
	int n;
	cout<<"请输入矩阵的阶数\n";
	cin>>n;
	double *a=(double*)malloc(sizeof(double)*n*n);
	double *b=(double*)malloc(sizeof(double)*n*n);
	input(a,n,n);
	for (int i=0;i<n;i++)
	for (int j=0;j<n;j++)
	b[i*n+j]=a[i*n+j];
	double res_of_det_a=det(b,n);
	if (res_of_det_a==0){cout<<"这个"<<n<<"阶矩阵的行列式值为0,不可逆\n";return ;}
	else cout<<"这个"<<n<<"阶矩阵的行列式值为"<<res_of_det_a<<"\n其逆为:\n"; 
	double *I=(double*)malloc(sizeof(double)*n*n);
	for (int i=0;i<n;i++)
	for (int j=0;j<n;j++){if (j==i)I[i*n+j]=1;
	else I[i*n+j]=0;
	}
	double **p=(double**)malloc(sizeof(double*)*n);
	double **I1=(double**)malloc(sizeof(double*)*n);
	for (int i=0;i<n;i++)p[i]=a+i*n,I1[i]=I+i*n;
	contrary(p,I1,n);
	for (int i=0;i<n;i++)//这里曾出现过一个问题,就是直接套用input函数却忘了进行行变换时input的输出顺序不变 
	{
		for (int j=0;j<n;j++)cout<<I1[i][j]<<" ";
		cout<<endl;
	}
//	cout<<endl;	print(*p,n,n);
	return;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值