1

現在、NxN 行列の行列式を見つけるプログラムを作成しようとしていますが、2 より大きい N の再帰に問題があります。私のデバッグオプションは、関数が列を通過することを示していますが、順序は決して下がらず、何があっても行列式がゼロになります。何が間違っているのかについてあらゆるアイデアを探してみましたが、答えが見つからないようです。私は非常に混乱しています:(。誰かが私のコードをざっと見て、どこが馬鹿なのか教えてくれたらとてもありがたいです!ここにあります)

コード:

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


double det(double **mat, int order);


int main (int argc, char* argv[])
{  


   FILE* input; 
   int row,column,N;
   double **matrix;
   N=3;
   matrix=(double**)malloc(N*sizeof(double));

   input=fopen("matrix.dat", "r");
   if(input !=(FILE*) NULL)
   {

      for(row=0; row<N; row++) 
      { 
     matrix[row]=(double*)malloc(N*sizeof(double));
  }
  for(row=0; row<N; row++) 
  {
        printf("| ");
        for(column=0; column<N; column++)   
        {  
          fscanf(input,"%lf ", &matrix[row][column]); 
      printf("%g ", matrix[row][column]);
    }
     if(row != (N/2))
         { 
       printf("|\n");
         }
         else
         {

           printf("|= %lf \n", det(matrix, N) );
     }
 }
 return(EXIT_SUCCESS);
 }

 else
 { 
  printf("*********************ERROR*********************\n");
  printf("** Cannot open input file 'matrix.dat' make  **\n");
  printf("** sure file is present in working directory **\n");
  printf("***********************************************\n");

  return(EXIT_FAILURE);
 }

}

double det(double **mat, int order)
{
 int debug;
 double cofact[order], determinant, **temp;
 determinant = 0;
 debug=0;

 if(order==1)
 {
  determinant=mat[0][0];

  if(debug==1)
  {
    printf("order 1 if\n");
  }
 }
  else if(order==2)
 {
 determinant= ((mat[0][0]*mat[1][1])-(mat[0][1]*mat[1][0]));

 if(debug==1)
 {
   printf("order 2 if\n");
     }
  }
 else
 {

  int column, rowtemp, coltemp, colread;
  for (column=0; column<order; column++) 
  {
  /* Now create an array of size N-1 to store temporary data used for calculating minors */
     temp= malloc((order-1)*sizeof(*temp)); 
    for(rowtemp=0; rowtemp<(order-1); rowtemp++)
  {
    /* Now asign each element in the array temp as an array of size N-1 itself */
    temp[rowtemp]=malloc((order-1)*sizeof(double));
  }
  for(rowtemp=1; rowtemp<order; rowtemp++)
  {
    /* We now have our empty array, and will now fill it by assinging row and collumn values    from the original mat with the aprroriate elements excluded */
       coltemp=0;
      for(colread=0; colread<order; colread++)
      {
        /* When the collumn of temp is equal to the collumn of the matrix, this indicates this row should be exlcuded and is skiped over */
        if(colread==column)
        {
          continue;
        }
        temp[rowtemp-1][coltemp] = mat[rowtemp][colread];
        coltemp++;
      }

   }
  if(debug==1)
  {
    printf("column =%d, order=%d\n", column, order);
  }
  determinant+=(mat[0][column]*(1 - 2*(column & 1))*det(temp, order-1));
}   

 }  
 return(determinant);   

 }
4

1 に答える 1

2
temp= (double **)malloc((order-1)*sizeof(double));

sizeof(double*) <= sizeof(double)これは、通常の32ビットまたは64ビットシステムの場合のように、クラッシュを引き起こすことはありませんが、概念的には間違っています。の配列にスペースを割り当てているdouble*ので、係数は、sizeof(double*)または、タイプが変更されたときに不変であるため、より適切である必要がありますsizeof *temp

temp = malloc((order-1) * sizeof *temp);

(そして、Cで結果をキャストする必要はありません。キャストmallocすると、忘れるなどのエラーが隠される可能性があるため、キャストしない方がよいでしょう#include <stdlib.h>。)

同じことが割り当てにも当てはまります

matrix=(double**)malloc(N*sizeof(double));

main

行列式の計算では、

         for(coltemp=0; coltemp<order; coltemp++)
         {
           for(colread=0; colread<order; colread++)
               {
               /* When the collumn of temp is equal to the collumn of   the matrix, this indicates this row should be exlcuded and is skiped over */
               if(colread==column)
               {
                continue;
               }
          temp[rowtemp-1][coltemp] = mat[rowtemp][colread];
          coltemp++;
            }
        }

列を2回ループしています。1回はforcoltemp == 0で、次に内側のループで時間coltempが増分order-1されるため、内側のループは開始時に2回実行さcoltemp == order-1れます。次にcoltemp、ループ内で再び複数回インクリメントされ、割り当てられたメモリの範囲外に書き込みます。

外側のループを削除coltemp = 0;する必要があり、内側のループが必要です。

pow(-1,column))

兆候を判断する良い方法ではありません。

(1 - 2*(column & 1))

の呼び出しよりも高速ですpow

最後に、main

for(row=0; row<N; row++) 
 {
    printf("| ");
    for(column=0; column<N; column++)   
    { 
          fscanf(input,"%lf ", &matrix[row][column]); 
          printf("%g ", matrix[row][column]);
    }
    if(row != (N/2))
    { 
    printf("|\n");
    }
    else
    {

            printf("|= %lf \n", det(matrix, N) );
    }
 }

行で行列式を印刷していますがN/2、これは見栄えがしますが、その時点ではまだ行列全体をスキャンしていないため、行N/2 + 1N-1は初期化されていないデータが含まれ、すべてゼロになる可能性は低くなります。をに変更するif (row != N/2)と機能しますif (row != N-1)が、それを処理する適切な方法は、行列のスキャンを計算および印刷から分離することです。これらはすべて独立した操作であり、独自の個別の機能で処理する必要があります。

于 2012-11-17T12:50:48.930 に答える