正在研究GTK+,争取尽快写出带有框体的程序,这个行列式的程序算是先写着练练手,感受一下递归调用函数吧,应该算是DFS吧,写起来实在是方便。
2014.3.3 修改
之前犯了很严重的错误,b[MAXNUM][MAXNUM]数组放在complemet_calculate函数内部,为自动变量,而返回的时候返回的b数组的指针,返回函数体内部声明定义的数组地址是很不安全的,之前能够正确运行的原因是函数结束时释放该自动变量,但该地址所拥有的数据暂时没有改动,系统知识标记了该部分数据可以修改,并不是进行数据的清空,所以指向该处的指针仍然可以正确读取数据。而一旦系统修改了这部分数据,程序就会出现不可预知的错误。
安全的做法应当是在不需要同时存在的情况下,把b数组声明为外部数组,就不会产生上述问题了。
2014.1.3 修改作
1.因为有了行列式计算的函数,于是就写了矩阵求逆的函数加了进去,现在已经可以计算行列式大小,输出伴随矩阵,输出余子式,代数余子式。矩阵的迹很好算,就先没有写,未来再加入计算A^2 ,计算矩阵的秩,计算矩阵特征值等等。(开始时因为只是想算行列式,输入函数写的时候只能输入为方阵,为了让函数有广泛适用性,添加着几个功能的时候应该还要修改一下输入函数。)
2.发现代数余子式的正负号似乎是错的,改了一下
#include <stdio.h>
#include <math.h>
#include <conio.h>
#define MAXNUM 100 //行列式最大大小
float b[MAXNUM][MAXNUM]; //complemet_calculate函数的临时数组,声明为外部变量防止数据丢失
float* complement_calculate(float a[][MAXNUM],int n,int x,int y) //余子式矩阵计算函数,返回一个n-1阶二维数组指针
{
int i,j,m,p;
memset(b,0,n-1);
for(i=0,m=0;i<=n-1;m++,i++)
{
if(i==(x-1))
{
m--
;
continue;
}
for(j=0,p=0;j<=n-1;p++,j++)
{
if(j==(y-1))
{
p--;
continue;
}
b[m][p]=a[i][j];
}
}
return b;
}
float determinant_calculate(float a[][MAXNUM],int n) //行列式计算函数
{
float result=0;
int i;
if(n==1)
return a[0][0];
else
{
for(i=0;i<=n-1;i++)
{
result+=pow(-1,1+(i+1))*a[0][i]*determinant_calculate(complement_calculate(a,n,1,i+1),n-1);
}
}
return result;
}
int determinant_input(float a[][MAXNUM]) //行列式输入函数,返回行列式大小n
{
int i,n=0,j;
char c;
for(i=0;i<=MAXNUM-1;i++)
{
scanf("%f%c",&a[0][i],&c);
n++;
if(c=='\n') break;
}
for(j=1;j<=n-1;j++)
{
for(i=0;i<=n-1;i++)
{
scanf("%f",&a[j][i]);
}
}
return n;
}
void show(float a[][MAXNUM],int n) //显示n阶矩阵函数,测试用
{
int i,j;
for(i=0;i<=n-1;i++)
{
for(j=0;j<=n-1;j++)
{
printf("%g ",a[i][j]);
}
printf("\n");
}
}
float *inverse_matrix_calculate(float a[][MAXNUM],int n) //逆矩阵计算函数,若不可逆,返回空指针NULL
{
float b[MAXNUM][MAXNUM];
memset(b,0,MAXNUM);
int i,j;
float determinant=determinant_calculate(a,n);
if(determinant==0)
return NULL; //若行列式的值为0,则矩阵不为可逆矩阵
else
for(i=0;i<=n-1;i++)
{
for(j=0;j<=n-1;j++)
{
b[j][i]=(pow(-1,i+1+j+1)*determinant_calculate(complement_calculate(a,n,i+1,j+1),n-1))/determinant; //这里i j位置互换以达到转置的目的
if(fabs(b[j][i])<=1.e-5) //消除误差
b[j][i]=0;
}
}
return b;
}
int main()
{
float a[MAXNUM][MAXNUM];
int n; //n为矩阵大小(n*n)
float *p;
memset(a,0,MAXNUM);
n=determinant_input(a);
p=inverse_matrix_calculate(a,n);
if(p!=NULL)
show(p,n);
else
printf("Error ! The matrix can not be inverted .");
getch();
return 0;
}