【问题标题】:Runtime error, NxN Matrix Inverse in C运行时错误,C 中的 NxN 矩阵逆
【发布时间】:2015-07-16 11:37:22
【问题描述】:

我正在尝试编写一个函数,它获取一个矩阵和维度(正方形),并返回 C 中的逆矩阵。 此外,我将使用它来求解最小二乘矩阵求解函数!

我从在线资源中获得了大部分想法和算法,并尝试根据我的程序进行更改。当我构建并运行它(在 Code::Blocks 和 ideone.com 在线编译器中)时,我得到运行时错误或不相关的结果。 如果有人可以帮助我,那就太好了。

这是我的代码:

/* Inverse of NxN matrix */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double CalcDeterminant(int D, double matrix[D][D])
{
  /* Conversion of matrix to upper triangular */
int i, j, k;
double ratio, det=1;
for (I = 0; I < D; i++) {
    for(j = 0; j < D; j++){
        if(j>i){
            ratio = matrix[j][i]/matrix[i][i];
            for(k = 0; k < D; k++){
                matrix[j][k] -= ratio * matrix[i][k];
            }
        }
    }
 }

 for(i = 0; i < D; i++)
 {
    det *= matrix[i][i];
 }

 return det;
}


double ** MatrixInverse(int size, double matrix[size][size])
{
int p,q,m,n,i,j,k;
double det;
double **m_inverse = (double **) malloc(sizeof(int) * size);
for (k = 0; k < size; k++) {
 m_inverse[k] = (double *) malloc(sizeof(int) * size);
}

double **dummy = (double **) malloc(sizeof(int) * size);
for (k = 0; k < size; k++) {
dummy[k] = (double *) malloc(sizeof(int) * size);
}
 /////////////////////////
 for (q=0;q<size;q++)
 {
     for (p=0;p<size;p++)
     {
         m=0;
         n=0;
         for (i=0;i<size;i++)
         {
             for (j=0;j<size;j++)
             {
                 if (i != q && j != p)
                 {
                    dummy[m][n]=matrix[i][j];
                    if (n<(size-2))
                    {
                       n++;
                    }
                    else
                    {
                        n=0;
                        m++;
                    }
                 }
             }
         }
        det = CalcDeterminant(size-1, dummy);
        printf("%f\n", det);
        m_inverse[q][p]=pow(-1,(q+p))*det;
     }
  }
  for (i=0;i<size;i++)
 {
     for (j=0;j<size;j++)
     {
         dummy[i][j]=m_inverse[j][i];
     }
 }
   det=CalcDeterminant(size, matrix);
 for (i=0;i<size;i++)
 {
     for (j=0;j<size;j++)
     {
         m_inverse[i][j]= dummy[i][j] / det;
     }
  }


 for(i = 0; i < size; i++)
    free(dummy[i]);
 free(dummy);    

return m_inverse;

}


int main()
{
int i, j;
int D = 5;
 // just an example matrix
double A[5][5] = {{1,2,3,4,6},
                  {6,1,5,3,8},
                  {2,6,4,9,9},
                  {1,3,8,3,4},
                  {5,7,8,2,5}};

printf("Original matrix\n");
for(i=0; i<D; i++)
{
    for(j=0; j<D; j++)
    {   
    //  A[i][j] = i+j-5;
        printf("%f\t", A[i][j]);
    }
    printf("\n");
} 
double **A_inverse = MatrixInverse(D, A); 
printf("Inverse Matrix\n");
for(i=0; i<D; i++)
{
    for(j=0; j<D; j++)
    {   
        printf("%f\t", A_inverse[i][j]);
    }
    printf("\n");
}

det = CalcDeterminant(D, A);
printf("%f\n", det);
return 0;
}

【问题讨论】:

  • 标准警告:不要像 malloc&friends 返回的那样转换 void *
  • 不要忽略编译器警告。您不理解的警告意味着您不知道自己在做什么。在没有警告之前,不要考虑尝试运行程序。
  • @n.m.:我完全同意,但是大多数编译器的标准警告实际上是不够的——尤其是对于初学者。应该始终启用-Wall,我通常建议添加-Wextra-Wconversion。后者应仔细观察。
  • 如果您正在对多项式进行最小二乘拟合,有办法避免必须反转矩阵。 opls.rtf.
  • @opls.rtf 感谢您的评论。我正在尝试通过计算 A 的伪逆来解决 AX=B 问题。您知道上述方法在这种情况下是否可行吗?

标签: c function matrix runtime-error matrix-inverse


【解决方案1】:

这一行包含一个重大错误,当sizeof(int) 不等于sizeof(int *) 时会导致问题(这通常发生在 64 位平台上):

double **m_inverse = (double **) malloc(sizeof(int) * size);

dummy的分配相同。

你正在分配一个 pointers 数组给 int,所以这里正确的是

double **m_inverse = malloc(sizeof(int *) * size);

稍后你这里有一个有问题的行:

det = CalcDeterminant(size-1, dummy);

通常,指向某种类型的指针与某种类型的数组数组相同(例如,请参阅this old answer of mine 以帮助您理解原因)。

【讨论】:

  • 感谢您的评论。所以你的意思是我应该插入 (sizeof(int) size) 代替?对不起,我不是很喜欢它。
  • @MRM 检查您的代码,是否缺少右括号?
  • 所以,现在分配完成了 :) 现在是行列式函数。我应该将其定义为 CalcDeterminant(int D, double **matrix) 吗?这种情况下我再次遇到运行时错误,并且不知道如何在 main 或 Inverse 函数中调用它。
  • @MRM 如果将参数声明为指针到指针,那么在从 main 函数调用矩阵时会出现问题,因此无论您如何操作,都必须返工不仅仅是CalcDeterminant函数。最简单的可能是在main 函数中分配和初始化矩阵,并让函数接受double ** 参数。
  • @MRM 另外,您应该学习如何使用调试器,因为这样您就可以“实际”捕获崩溃,并准确查看代码中发生的位置,并且还可以检查函数调用堆栈以及所涉及变量的值。
【解决方案2】:

分配内存时,始终使用正确的大小类型。您可以在任何地方使用sizeof(int),即使需要double指针。提示:使用sizeof(*&lt;pointer you assign the result to&gt;)。这样,您始终使用正确的尺寸。

注意:不要将void * 转换为malloc 和朋友返回的内容。

【讨论】:

  • 所以正如我对 Joachim 所说,这只是一个函数的一小部分,que 中有 2 个主要的函数调用。而且我是初学者(刚刚使用matlab!)。如果 double ** Func(...) 适合返回二维数组,您建议使用什么?我尝试了很多类型,都来自在线资源,但这是最适合程序其余部分的类型。
  • @MRM:这是一个指向double 的指针数组。我强烈推荐读一本 C 书;这将涵盖所有基础知识。请理解,我们无法在此处提供有关该内容的教程,但这对于理解 C 至关重要。没有这些知识,您最终将陷入下一个 tar-pit。二维数组实际上与一维数组一样通过&lt;type&gt; * 传递。语义在 C 中是非正式的。
  • 谢谢@Olaf。我只是在关注这个:gsamaras.wordpress.com/code/2d-dynamic-array-c>
  • @MRM:盲目地遵循一些互联网食谱总是是个坏主意。您可能会先想到一个想法,然后在书籍或教程中查找您不理解的概念(两者都可以免费或花钱找到)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-08
  • 2014-11-14
  • 1970-01-01
相关资源
最近更新 更多