• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C言語★)

C言語での行列計算に関する問題

このQ&Aのポイント
  • セグメントエラーが発生している C 言語の行列計算関数とプログラムについて相談しました。
  • 関数 matprod の引数やループ処理に問題がある可能性があります。
  • 間違いを見つけることができる方にお教えいただきたいです。

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★追記。 ・ちょっと同じような処理を書いてみました。  解説はしませんのでソースを読み取ってみて下さい。  でも注目して欲しい点は  (1)new_matrix 関数の行列確保  (2)free_matrix 関数の行列解放  (3)disp_matrix 関数の行列表示  の3つです。 ・2次配列を動的に確保していますが malloc(calloc)、free の回数が少ないです。  この方法ならメモリ不足で free したり、行列解放の free の回数がわずか 2 回です。  過去質問を参考にどうぞ。  http://oshiete1.goo.ne.jp/qa3022605.html→『callocで二次元配列を作成するには?』 ・では下のソースをご覧下さい。 ソース: #include <stdio.h> #include <stdlib.h> // 行列の確保 double **new_matrix( int nrow, int ncol ) {  double **aa;  double *a;  int i;    if ( (aa = (double **)calloc(nrow + 1,sizeof(double*))) != NULL ){   if ( (a = (double *)calloc(nrow * ncol,sizeof(double))) != NULL ){    for ( i = 0 ; i < nrow ; i++ ){     aa[ i ] = &a[ i * ncol ];    }    aa[ nrow ] = NULL;  // 行数の末尾判定の工夫    return aa;    // 正常   }   free( aa );  }  return NULL;     // 確保エラー } // 行列の解放 void free_matrix( double **a ) {  if ( a != NULL ){   free( a[0] );   free( a );  } } // 行列の表示 void disp_matrix( double **a, int nrow, int ncol ) {  int x, y;    for ( y = 0 ; y < nrow ; y++ ){   for ( x = 0 ; x < ncol ; x++ ){    printf( "%.f ", a[y][x] );   }   printf( "\n" );  }  printf( "\n" ); } // 行列の初期化(ダミーセット) void dummy_matrix( double **a, int nrow, int ncol ) {  int x, y;    for ( y = 0 ; y < nrow ; y++ ){   for ( x = 0 ; x < ncol ; x++ ){    a[ y ][ x ] = ncol * y + x;   }  } } // 行列処理 void matprod( int nrow, int ncol, double **a, double **b, double **prod ) {  int i, x, y;    for ( y = 0 ; y < nrow ; y++ ){   for ( x = 0 ; x < ncol ; x++ ){    for ( i = 0 ; i < ncol ; i++ ){     prod[ y ][ x ] = a[i][x] * b[y][i];    }   }  } } // メイン関数 int main( void ) {  int success = 0; // 成功フラグ  int nrow = 3;  // 行数  int ncol = 3;  // 列数  double **a, **b, **prod;    // 3×3行列を3つ確保  if ( (a = new_matrix(nrow,ncol)) != NULL ){   if ( (b = new_matrix(nrow,ncol)) != NULL ){    if ( (prod = new_matrix(nrow,ncol)) != NULL ){     // aの初期化,表示     dummy_matrix( a, nrow, ncol );     disp_matrix( a, nrow, ncol );     // bの初期化,表示     dummy_matrix( b, nrow, ncol );     disp_matrix( b, nrow, ncol );     // 行列の計算,表示     matprod( nrow, ncol, a, b, prod );     disp_matrix( prod, nrow, ncol );     success = 1;     free_matrix( prod );    }    free_matrix( b );   }   free_matrix( a );  }  if ( success == 0 ){   printf( "3×3行列をメモリ確保できませんでした。\n" );   return 1;  }  return 0; } 以上。

その他の回答 (3)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★追記。 >肝心の計算結果が出てきません。。><・・。  ↑  これって計算結果が正しくないという意味ですか? ・matprod 関数は行列の掛け算ですよね?  だとすると行列の計算ロジックが間違っていますね。  間違い⇒prod[ y ][ x ] = a[i][x] * b[y][i];  正しい⇒prod[ y ][ x ] += a[i][x] * b[y][i];  となりませんか。 ・以上。回答 No.3 の matprod 部分も修正して下さい。

参考URL:
http://www.geocities.jp/supermisosan/matrixmultiply.html
danzania
質問者

お礼

Oh-Orangeさん。 何度も私の初歩的な質問にご回答ありがとうございました。 無事にプログラムを作成することができました!! プログラミングが楽しく思えました★ Oh-Orangeさんみたいな人がこの教えてgooにいることを嬉しく思います>< 本当にありがとうございます!!!

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★アドバイス >肝心の計算結果が出てきません。。><・・。  ↑  これは正しい計算結果が出ないのでしょうか?  それとも全く計算結果が表示されないのでしょうか?  どういう意味? >助けてください!!!!  ↑  どこの何を。  せめてどの関数のどの場所か補足してくれないとね。  行列プログラムのようですね。  行列の計算方法を忘れてしまいました。 ・とりあえず prod がメモリ確保されていないのでバグとなっています。  行列の為に2次配列を動的確保しているのならば matprod 関数の引数は最初の方法に  戻して下さい。それであっているので。  ちなみに『セグメントエラーで実行できません。』というのは prod が確保されていない  エラーです。これが原因でした。  まずはソースを最初の『double **a』に引数を戻してから prod を new_matrix 関数で  確保して下さい。 ・以上。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★関数の引数定義を修正しましょう。 ・間違い⇒double **a  正しい1⇒double (*a)[3]  正しい2⇒double a[3][3]  ※同様に『b』『prod』も修正します。 もう一つの方法: ・配列の要素が可変の場合は引数を『**a』として  for ( k = 0 ; k < ncol ; k++ ){   double aa = a[ k * ncol + j ];   double bb = b[ i * ncol + k ];   prod[ i * ncol + j ] = aa * bb;  }  と配列位置を計算してアクセスします。 ・以上。

danzania
質問者

補足

#include <stdio.h> #include <stdlib.h> double * vector; double ** matrix; double * new_vector(int n); /* n×1 ベクトルの作成 */ double ** new_matrix(int nrow, int ncol); /* nrow行ncol列の行列の作成 */ void free_vector(double * v); /* ベクトルの消去 */ void free_matrix(double ** a); /* 行列の消去 */ void vecprint(double * v, int n); /* n×1 ベクトルの表示 */ void matprint(double ** a, int ncol); /* 行列の表示 */ /* ベクトルv1とベクトルv2の和をベクトルsumに代入する */ void vecsum(int n, double * v1, double * v2, double * sum); void matprod(int nrow,int ncol,double a[3][3],double b[3][3],double prod[3][3]); int main() { int i, j, nrow, ncol; double *v1, *v2, *v3; double **a,**b,**prod; nrow = 3; /* 行の数 */ ncol = 3; /* 列の数 */ a = new_matrix(nrow, ncol); /* 行列を作る */ for (i = 0; i < nrow; i++) for (j = 0; j < ncol; j++) a[i][j] = 1.0 * i + j; /* 行列の要素の代入 */ printf("%d × %d 行列:\n", nrow, ncol); matprint(a, ncol); /* 出力 */ b = new_matrix(nrow, ncol); /* 行列を作る */ for (i = 0; i < nrow; i++) for (j = 0; j < ncol; j++) b[i][j] = 1.0 * i + j; /* 行列の要素の代入 */ printf("%d × %d 行列:\n", nrow, ncol); matprint(b, ncol); /* 出力 */ matprod(3,3,a,b,prod); for(i=0;i<nrow;i++){ for(j=0;j<ncol;j++){ printf("%lf",prod[i][j]); //3*3の計算をして、答えを表示する。 }} return; } double * new_vector(int n) { double * v; v = malloc(sizeof(double) * n); if (v == NULL){ fprintf(stderr, "\n記憶領域不足.\n"); exit; } return v; } double ** new_matrix(int nrow, int ncol) { int i; double ** a; a = malloc((nrow + 1) * sizeof(void *)); if (a == NULL){ fprintf(stderr, "\n記憶領域不足.\n"); exit; } for (i = 0; i < nrow; i++) { a[i] = malloc(sizeof(double) * ncol); if (a[i] == NULL) { while (--i >= 0) free(a[i]); free(a); fprintf(stderr, "\n記憶領域不足.\n"); exit(EXIT_FAILURE); } } a[nrow] = NULL; /* 行の数を自動判断するための工夫 */ return a; } void free_vector(double * v) { free(v); } void free_matrix(double ** a) { double ** b; b = a; while (*b != NULL) free(*b++); free(a); } void vecprint(double * v, int n) { int j; for (j = 0; j < n; j++) { printf("%0.f ", v[j]); } printf("\n"); } void matprint(double ** a, int ncol) { int i; for (i = 0; a[i] != NULL; i++) { vecprint(a[i], ncol); } } void vecsum(int n, double * v1, double * v2, double * sum) { int i; for(i=0; i<n; i++) sum[i] = v1[i] + v2[i]; return; } void matprod(int nrow,int ncol,double a[3][3],double b[3][3],double prod[3][3]){ int i,j,k; for(i=0;i<nrow;i++){ for(j=0;j<ncol;j++){ for(k=0;k<ncol;k++){ prod[i][j]=a[k][j]*b[i][k];} } } } このプログラムを動かそうとしています。 セグメントエラーはなくなったのですが・・・。 肝心の計算結果が出てきません。。><・・。 助けてください!!!!

関連するQ&A