矩阵求逆及行列式求值 - 未来再来添点更多矩阵计算功能

   正在研究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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值