C语言求矩阵的行列式、伴随矩阵、逆矩阵

CSDN大神编写的求矩阵的行列式,int getA(int arcs[N][N],int n),通过调用递归函数,按矩阵的第一行进行分解,虽然行列式的计算都学过,但是自己写起来还是得费一番功夫的,好在有MATLAB可以验证结果,结果对拿过来就可以直接用。

void getAStart(int arcs[N][N],int n,int ans[N][N]),求矩阵的伴随矩阵,也需要调用求矩阵的行列式。原文地址:

点击打开链接http://blog.csdn.net/abcjennifer/article/details/6693612

验证算法计算速度,当我用C调用去求一个10阶矩阵的行列式和伴随矩阵时,跑10条数据大概用7秒的时间(自己其他函数占用很小时间),但是当矩阵变成15阶时,感觉就计算不出来了,每增加一阶,算法的复杂度都成倍的增长。

无奈计算速度太慢,又需要快速处理大量数据,只好优化算法了,本文绝对算的上是懒人,能找到现成的绝对不自己写!网上搜了下,LU分解貌似效率更高一点,结果找到一篇靠谱的文档:点击打开链接http://www.docin.com/p-690103638.html

文献对矩阵分解的原理进行了详细介绍,当初矩阵分析学的不好,也没仔细看,只可惜找到它太晚,以至于找到他时,我已经照着下面的MATLAB代码把LU分解的C代码写完了,

MATLAB代码如下:

function [L,U]=myLU(A)  
 
%实现对矩阵A的LU分解,L为下三角矩阵  
 

 
[n,n]=size(A);  
 
L=zeros(n,n);  
 
U=zeros(n,n);  
 
for i=1:n  
 
L(i,i)=1;  
 
end  
 
    for k=1:n  

        for j=k:n  

        U(k,j)=A(k,j)-sum(L(k,1:k-1).*U(1:k-1,j)');  


        %U(k,j)
        end  

        for i=k+1:n  

        L(i,k)=(A(i,k)-sum(L(i,1:k-1).*U(1:k-1,k)'))/U(k,k);  
        %L(i,k)
        end  



    end  

短短几行代码让人用C写的那叫一个痛苦。

参考那个文档把LU 分解后L矩阵(下三角)和U矩阵(上三角)求逆的直接展过来用,对着MATLAB结果,终于对了,不容易啊。用C写程序觉对是需要耐心,MATLAB求行列式一个det就可以了,求逆inv,求伴随是啥命令给忘了,不过直接掉det(A)*inv(A),  得出来的就是伴随矩阵。

验证结果很简单,A=L*U,那么inv(A)=inv(U)*inv(L);

搞定

void myLU(double A[COLUMN][COLUMN],double Low[COLUMN][COLUMN],double Up[COLUMN][COLUMN],int n)
{
	int i,j,k,t,q;
	//double Low[COLUMN][COLUMN]={0};
	double temp1[COLUMN]={0};
	double temp2[COLUMN]={0};
	double temp3=0;
	for (i=0;i<n;i++){
		for(j=0;j<n;j++){
			if(i==j)
		Low[i][i]=1;
		}
	}
	/*Low[0][0]=1;Low[1][1]=1;Low[2][2]=1;Low[3][3]=1;Low[4][4]=1;
	Low[5][5]=1;Low[6][6]=1;Low[7][7]=1;Low[8][8]=1;*/
	
	for(k=0;k<n;k++){
		for(j=k;j<n;j++){

		//U(k,j)=A(k,j)-sum(L(k,1:k-1).*U(1:k-1,j)');  
		/*fetch_matrix_L(Low,temp1,k);
		fetch_matrix_U(Up,temp2,k,j)*/;
		if(k==0){
			temp3=0;
		}
		else{
				for(i=0;i<=k-1;i++){
				temp1[i]=Low[k][i];//L(k,1:k-1)
				}		
				for(i=0;i<=k-1;i++){
				temp2[i]=Up[i][j];//U
				}		
				temp3=0;
				for(i=0;i<=k-1;i++){
				temp3+=temp1[i]*temp2[i];//点乘,求和
				}
		}
		
			
		Up[k][j]=A[k][j]-temp3;
		//printf("%d----%d-----%f\n",k,j,Up[k][j]);
		}
		//下三角
		memset(temp1,0,sizeof(double));
		memset(temp2,0,sizeof(double));
		temp3=0;
		for(t=k+1;t<n;t++){
		/*fetch_matrix_L(Low,temp1,k);
		fetch_matrix_U(Up,temp2,k,k);*/
			if(k==0){
				temp3=0;
			}
			else
			{
				for(i=0;i<=k-1;i++){
				temp1[i]=Low[t][i];//L(k,1:k-1)
				}		
				for(i=0;i<=k-1;i++){
				temp2[i]=Up[i][k];//U
				}		
				temp3=0;
				for(i=0;i<=k-1;i++){
				temp3+=temp1[i]*temp2[i];//点乘,求和
				}

			}
			Low[t][k]=(A[t][k]-temp3)/Up[k][k];
			//printf("%d----%d-----%f\n",k,j,Low[t][k]);
		}
	
	}


}

上述代码实现矩阵的LU分解,写这一段可费了不少劲,好在有MATLAB,结果不对,就一步步的跟,总能找到错误在哪里?大不了MATLAB里 打个断点,C里面我设个断点。每走一步观察一下结果。

矩阵分解完后后,便是求各自的逆运算了。也懒得单独写一个函数了,copy代码。

//--------------test-------------------------
	//dTemp=dTemp_test;复制测试数组,zuduan
	/*for(i=0;i<9;i++){
	memcpy(dTemp[i],dTemp_test[i], sizeof(double)*9);
	}*/
//-------------------------------------------
	//det_A=getA(dTemp,piRowLenth[3]);//|A|,被det_AAA取代
	//printf("%1.5e\n",det_A);//real data
//------------test LU 分解-------------------
	
	myLU(dTemp,Temp11,Temp22,9);//注意temp1与temp2下面是否复用
	det_AA=Temp11[0][0];
	for(i=1;i<9;i++){
	det_AA*=Temp11[i][i];
	}
	det_AAA=Temp22[0][0];
	for(i=1;i<9;i++){
	det_AAA*=Temp22[i][i];
	}
	det_AAA=det_AAA*det_AA;
//	printf("%1.5e\n",det_AAA);
	det_A=det_AAA;


//-----求L和U(Temp22)的逆------------------------------------------
	for(i=0;i<9;i++){
	u[i][i]=1.0/Temp22[i][i];
		for(k=i-1;k>=0;k--){
		dDataSun=0;
		for(j=k+1;j<=i;j++)
		dDataSun=dDataSun+Temp22[k][j]*u[j][i];
		u[k][i]=-dDataSun/Temp22[k][k];
		
		}
	}
//--------求L(temp11)------------------------------------
	for (i=0;i<9;i++){
		l[i][i]=1;
		for(k=i+1;k<9;k++){
			 for(j=i;j<=k-1;j++)
				l[k][i]=l[k][i]-Temp11[k][j]*l[j][i];
				}
	
	}

//--------------求L与U乘积
	for(i=0;i<9;i++){
		for(j=0;j<9;j++){
			for(k=0;k<9;k++)
		dTemp3[i][j]+=u[i][k]*l[k][j];
		//	printf("%d---%d----%f\n",i,j,dTemp3[i][j]);
		}
	}
好了,记录到这,可惜CSDN不能直接上传附件,不然直接把写的分类函数的C和H文件放上来。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值