计算矩阵逆的问题

时间:2019-07-03 09:14:01

标签: c

我正在尝试计算任意等级N x N的方阵的逆。我正在使用一种结构来存储矩阵的值,我可以有效地对其求值,并且我已经能够计算行列式。但是逆函数一定存在一些问题。这是代码

    struct m{
        size_t row;
        size_t col;
        double *data;
    };

    void inverse(size_t n, struct m *A) /*Calculate the inverse of A */
{
    size_t i,j,i_count,j_count, count=0;
    double det = determinant(n, A);
    size_t id = 0;    
    double *d;

    struct m C; /*The Adjoint matrix */
    C.data = malloc(sizeof(double) * n * n);

    C.row = n;
    C.col = n;    

    struct m *minor; /*matrices obtained by removing the i row and j column*/

    if (!(minor = malloc(n*n*(n+1)*sizeof *minor))) {
        perror ("malloc-minor");
        exit(-1);
    }    

    if (det == 0){
        printf("The matrix is singular\n");
        exit(1);
    }    

    for(id=0; id < n*n; id++){
        d = minor[id].data = malloc(sizeof(double) * (n-1) * (n-1));
        for(count=0; count < n; count++)
        {
            //Creating array of Minors
            i_count = 0;
            for(i = 0; i < n; i++)
            {
                j_count=0;
                for(j = 0; j < n; j++)
                {
                    if(j == count)
                        continue; // don't copy the minor column element
                    *d = A->data[i * A->col + j];
                    d++;
                    j_count++;
                }
                i_count++;
            }
        }
    }

    for(id=0; id < n*n; id++){
        for(i=0; i < n; i++){
           for(j=0; j < n; j++) 
            C.data[i * C.col + j] = determinant(n-1,&minor[id]);//Recursive call
        }
    }

    transpose(&C);
    scalar_product(1/det, &C); 
    *A = C;    
}

行列式是使用以下算法递归计算的:

double determinant(size_t n, struct m *A)
    {                                    
        size_t i,j,i_count,j_count, count=0;

        double det = 0;

        if(n < 1)
        {
            printf("Error\n");
            exit(1);
        }

        if(n==1) return A->data[0];

        else if(n==2) return (A->data[0]* A->data[1 * A->col + 1] - A->data[0 + 1] * A->data[1*A->col + 0]);    

        else{
            struct m C;

            C.row = A->row-1;
            C.col = A->col-1;

            C.data = malloc(sizeof(double) * (A->row-1) * (A->col-1));

            for(count=0; count < n; count++)
            {
                //Creating array of Minors
                i_count = 0;
                for(i = 1; i < n; i++)
                {
                    j_count=0;
                    for(j = 0; j < n; j++)
                    {
                        if(j == count)
                            continue; // don't copy the minor column element
                        C.data[i_count * C.col + j_count] = A->data[i * A->col + j];
                        j_count++;
                    }
                    i_count++;
                }
                det += pow(-1, count) * A->data[count] * determinant(n-1,&C);//Recursive call
            }
            free(C.data);
            return det;
        }
    }

您可以在此处找到完整的代码:https://ideone.com/gQRwVu

2 个答案:

答案 0 :(得分:0)

在:之后的循环中使用其他变量:

det + =pow(-1,count) * A->data[count] *determinant (n-1,&C)

答案 1 :(得分:0)

您对逆的计算不太符合e中描述的算法。 G。对于Inverse of a Matrix using Minors, Cofactors and Adjugate,甚至考虑到您现在省略了仲裁和划分步骤。将for中最外面的inverse()循环与此有效的实现进行比较:

double Rdata[(n-1)*(n-1)];              // remaining data values
struct m R = { n-1, n-1, Rdata };       // matrix structure for them
for (count = 0; count < n*n; count++)   // Create n*n Matrix of Minors
{
    int row = count/n, col = count%n;
    for (i_count = i = 0; i < n; i++)
        if (i != row)                   // don't copy the current row
        {
            for (j_count = j = 0; j < n; j++)
                if (j != col)           // don't copy the current column
                    Rdata[i_count*R.col+j_count++] = A->data[i*A->col+j];
            i_count++;
        }
    // transpose by swapping row and column
    C.data[col*C.col+row] = pow(-1, row&1 ^ col&1) * determinant(n-1, &R) / det;
}

对于给定的输入数据,它会产生正确的逆矩阵

1  2 -4.5
0 -1  1.5
0  0  0.5

(已经转置并除以原始矩阵的行列式)。

次要注意事项:

  • *A = C;末尾的inverse()丢失了*A的原始数据指针。
  • 格式化函数f()对于负值是错误的,因为在这种情况下 fraction 也是负数。您可以写if (fabs(f)<.00001)