• 締切済み

C言語で行列表現

C言語の講習で2×2行列の表現方法を考えると云う問題に直面しました。 当初は行列の要素ごとをscanfで記憶、対応させて掛け算等の演算を行おうと考えていましたが 汎用性の面から外部のテキストを読み込み、結果をテキストに書き込んで出力するような プログラムにしたいと考えました。 当方の疑問として 行列の宣言を int a[ ][ ];と宣言した後(今回ですとa[2][2]と宣言するのが正しいのですが) 各要素にファイルの値を当てるにはどういったプログラムを書けばいいんでしょうか? 講師からはアドレス、構造体、配列、mallocないしallocを使えとのアドバイスを受けましたが 行列表現の段階で躓いていて今後の指針含めて正直よく分かりません。 部分部分で構いませんので、どなたか解説をお願いいたします。 m(_ _)m P.S 表記の面で判りづらい点がありましたら遠慮なく指摘してください。 熟読の上改訂いたします。

  • ageb
  • お礼率78% (18/23)

みんなの回答

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.5

#2です >変数x,yを整数型で宣言 行列の要素数を宣言しています(とりあえず2×2とのことだったので両方2にしています) >forのループで行列を表現してるんでしょうか? そういうことになります(コメントだけでは不十分だったですか?) 別にforループである必要はありませんが下手にわけわからん 変数名出たりすると逆にわかりにくいだろうと思って あえてforループで書いているだけです 雑な一例と書いたようにそれなりに雑な書き方をしています 後は質問者さんが工夫すればいいだけの話なので (ファイルから行列の要素数と各データを求めるにしてもそこは工夫次第でどうにでもなる話) 今回部分部分を切り出して説明する方法が思いつかなかったので こういった一連の流れを書いています (基本的に丸投げ質問に答えるのは嫌いです 今回分からない部分がある程度明確化されているので回答しました)

ageb
質問者

お礼

ありがとうございました。

  • hrsmmhr
  • ベストアンサー率36% (173/477)
回答No.4

先の回答でも申しましたが、どのように行列を記述するかは自由です 先の例では ファイルの先頭から 1 2 3 4  //(区切りになる文字が空白ではなかったかもしれないのでご確認ください) となっているのを読み込みます ファイル内の移動はポインタの値を操作するのですが、 そのあたりの関数はCのほうで用意されていたような気がします (もしなかったら自作です) 見やすくするなら行列名をコメント記号を決めて書くのも自由かと思います 勉強なさっているのなら、参考書もお持ちでしょうからそこらあたりいろいろ工夫されてみては いかがでしょうか

ageb
質問者

お礼

そうですね、一度試行錯誤してみようと思います。 回答ありがとうございました

  • hrsmmhr
  • ベストアンサー率36% (173/477)
回答No.3

やりたいことから推測しますと fopenでファイルを開いてfscanfか何かでファイル上の自分で決めたフォーマットで読み込み 2次元配列に受け渡すんだと思います fscanf(fp, "%d%d%d%d", &a[0][0], &a[0][1], &a[1][0], &a[1][1]); みたいにもできると思います

ageb
質問者

補足

お返事ありがとうございます。 おっしゃるとおり、txtファイルないしexcelから 行列を読み込もうと考えています。 踏み込んでお聞きしたいのですが 行列のフォーマットを A 1 2 3 4 とした場合、行列の名前であるAをスキャンせず 数値だけをスキャンする場合、どうすればいいのでしょうか。 自分自身で考えたのは %_ の文字を変える(?) 表示はファイル全体だがスキャンは数値に限定する ぐらいなんですが……。 P.S 考え付いたものは本当にC言語を租借し切れていない初心者の発想ですのでお目汚しになってしまわれたら申し訳ありません。

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.2

考え方次第で書き方はいろいろあると思いますが 雑な一例  int x = 2;  int y = 2;  int *data = (int *)malloc(sizeof(int) * x * y);  for (int yy = 0 ; yy < y ; yy ++ ) {   for (int xx = 0 ; xx < x ; xx ++ ) {    *(data + yy * x + xx) = 1; //data[yy][xx] に相当   }  }  free(data);

ageb
質問者

補足

変数x,yを整数型で宣言 forのループで行列を表現してるんでしょうか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

とりあえず 1点確認: 今問題に挙がっているのは「2×2行列」ですが, 本来はより一般的に m×n行列であるべきものですか? それとも, 「2×2行列さえできればいい」ということでしょうか?

ageb
質問者

補足

遅ればせながら返答させていただきますと 課題として前者に取り組んでいますが、自身の中では汎用性の面からm×n行列の処理を出来ないかと考えております。

関連するQ&A

  • 行列をベクトルに(C言語)

    行列をベクトルに(C言語) m行n列の行列Aがあったとき、それをm×n行1列の行列(ベクトル)Bに するというプログラムを作りたいです。 これは、行列Aの1列目m行分の要素をそのまま行列Bの1行1列目に持っていき、 それを行列Aのn列の数だけ繰り返す、といった要領です(画像参照) つまり MATRIX B; B.m=A.m*A.n; B.n=1; return B; ということだと思うのですが、なかなかうまいくいきません。 また、構造体も使いたいので、 typedef struct { int m; int n; double *mat; } MATRIX; と宣言しました。 画像は説明のため、一応載せておきました。(例として4列の行列になっています) みなさんよろしくお願いします。

  • 行列式のプログラム

    適当な形式にて初期化された2つの2次元配列により、3×4行列Aと4×3行列Bの要素を表現し、積ABを求めて表示させるプログラムなんです。 ここまでならなんとかなるかもと思ったんですが、行列はAはプログラム中で以下の数値で初期化して、行列Bの要素はキーボードから入力させるようにしないといけないんです。。   2.0 3.0 4.0 5.0 A= 3.0 4.0 5.0 6.0   1.0 2.0 3.0 4.0 なんですけれども、教えていただけたらうれしいです。。 お願いします!!

  • 部分行列の抜き出し(C言語)

    部分行列の抜き出し(C言語) ある行列から、任意の部分行列を抜き出すような関数を作りたいのですが、わからないので手助けをお願いしたいです。 たとえば4行4列の行列Aがあった場合、その2行2列、2行3列、3行2列、3行3列目の 4つの(2行2列の)要素を抜き出すような関数です。 枠組みは出来ているので載せておきます。 #include <stdio.h> #include <stdlib.h> #include <math.h> typedef struct matrix{ double *data; int size[2]; }MATRIX; MATRIX create_matrix(int m,int l,int a); //行列の作成 void print_matrix(MATRIX A); //行列の表示 MATRIX submatrix(MATRIX matrix_A,int m,int n,int l,int k); //任意の部分行列の抜き出し int main(int argc,char **argv) { //構造体の初期化 MATRIX matrix_A={NULL,NULL,NULL}; MATRIX matrix_B={NULL,NULL,NULL}; MATRIX matrix_C={NULL,NULL,NULL}; int m=0; //行列の行 int l=0; //行列の列 int a=1; //要素 double det=0; //行列計算 //行列Aの作成 m=4;//行 l=4;//列 matrix_A = create_matrix( m, l, a); //関数 matrix_C = submatrix(matrix_A,2,2,3,3); //行列結果出力 printf("\n\tmatrix input"); print_matrix(matrix_A); printf("\n\tmatrix output"); print_matrix(matrix_C); //行列の開放 free(matrix_A.data); matrix_A.data=NULL; free(matrix_C.data); matrix_C.data=NULL; printf("終了!\n\n"); return 0; } MATRIX create_matrix(int m,int l,int a) { MATRIX matrix_A={NULL,NULL,NULL}; int i=0; //サイズの確保 行;size[0] 列;size[1] matrix_A.size[0]=m; matrix_A.size[1]=l; //メモリの確保 matrix_A.data=(double *)malloc(sizeof(double)*matrix_A.size[0]*matrix_A.size[1]); if(matrix_A.data == NULL){ printf("メモリ確保失敗!![matrix_A]\n"); exit(1); } //行列Aの作成 for(i=0; i<((matrix_A.size[0])*(matrix_A.size[1])) ;i++){ *(matrix_A.data+i)=a+i; } return(matrix_A); } /*行列の表示*/ void print_matrix(MATRIX matrix_A) { int i=0; int j; //行 int k; //列 printf("\n行列の表示\n"); //行列Aのプリント for(j=0;j<matrix_A.size[0];j++){ for(k=0;k<matrix_A.size[1];k++){ printf("%f\t",*(matrix_A.data+k*matrix_A.size[0]+j)); } printf("\n"); } return; } MATRIX submatrix(MATRIX matrix_A,int m,int n,int l,int k) { MATRIX matrix_C = {NULL,NULL,NULL}; int i,j; //サイズの確保 行;size[0] 列;size[1] matrix_C.size[0]=l-m+1; matrix_C.size[1]=k-n+1; //メモリの確保 matrix_C.data=(double *)malloc(sizeof(double)*matrix_C.size[0]*matrix_C.size[1]); if(matrix_C.data == NULL){ printf("メモリ確保失敗!![matrix_C]\n"); exit(1); } //任意の部分行列の抜き出し (ここがわかりません。) } よろしくお願いします。

  • C言語を用いた45×45の逆行列の表示について・・・・。。

    次のプログラムを動かすと逆行列を求めることができます。 10×10の計算までは、スムーズに計算する事ができたのですが、 私が知りたい45×45の行列の計算になるとなぜかうまくいきません。 そこでみなさんにお聞きしたいのは、計算がうまくいかない理由がプログラムにあるのか、単にPCの限界なのか、それ以外なのか。みなさんからアドバイスをいただけないでしょうか? ※下のプログラム、見づらくてすいません。 #include <stdio.h> #define N 10 /* 元の数 */ #define N2 2*N /* プロトタイプ宣言 */ void Print(int k); /* 大域変数 */ double a[N][N2]= {/* 行列 Aおよび単位行列 */ { ここに45×45の正則行列&45×45の単位行列を入れます・・・。。 }; int main(void) { double d; int i,j,k; for (k=0;k<=N-1;k++) { Print(k); for(i=0;i<=N-1;i++) { if(i!=k) { d=a[i][k]/a[k][k]; for (j=k+1;j<=N2-1;j++) a[i][j]=a[i][j]-a[k][j]*d; a[i][k] = 0.0; } } d=a[k][k]; for (j=k;j<=N2-1;j++) a[k][j]=a[k][j]/d; } Print(N); } void Print(int k) { int i,j; printf("\n ステップ %d \n",k); /* 小見出し */ for(i=0;i<=N-1;i++) { /* 第i行を印刷 */ for(j=0;j<=N-1;j++) printf("%6.4f,",a[i][j]); printf(" : "); for(j=N;j<=N2-1;j++) printf("%6.4f,",a[i][j]); printf("\n"); } }

  • 多次元配列の行列

    1番 キーボードから3×3の行列の要素を2次元配列に入力した後、その値を表示するプログラムをさくせいせよ 2番 キーボードから3×4の行列の要素を2次元配列に入力した後、転置行列を出力するプログラムをさくせいせよ 3番 2つの行列A(3×3行列)、B(3×3行列)の買う要素の値をキーボードから2つの配列に入力し、2つの行列、並びに、それらの和、差、積の行列を出力するプログラムを作成せよ(Bに単位行列を入れて検算せよ) 4番 2行3列の行列と3行2列の積を求めるプログラムを作成せよ どなたかわからないでしょうか?? 数が多くてすみません。 わかる方お願いします!!

  • c言語のプログラムで行列の積を計算する

    指定された行・列数(それぞれ10以下とする)の行列 X, Y の積 Z = X × Y を求めるプログラムを作成せよ.行列の要素はすべて整数とする. このプログラムで行と列の成分を入力するときに、1列になってしまうのですがどうしたらちゃんと入力できますか? int main(void) { double A[10][10]; double B[10][10]; int i,j,m,n,p,k; printf("行列xの行数は?:"); scanf("%d",&m); printf("行列xの列数(行列yの行数)は?:"); scanf("%d",&n); printf("行列yの列数は?:"); scanf("%d",&p); printf("行列xを入力してください。\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &A[i][j]); } } printf("行列yを入力してください。\n"); for (i = 0; i < n; i++) { for (j = 0; j < p; j++) { scanf("%d", &B[i][j]); } }

  • 行列の要素にベクトルの成分をいれる?

    ベクトルの成分を行列にするというのは習いました。 では、ベクトルを並べて 例えば 2次元のベクトルA,BとベクトルC,Dがあり、それぞれを並べて ( (2,1) , (3.5) ) と ( (2,4), (1.6) ) というようにして、A,Cの内積、B,Dの内積が入った行列を導出するようなことはできますか? (A,B)・(C,D) = (A・C , B・D) 仮にベクトルの成分行列を要素に持つ行列があると仮定して、(C,D)行列を転置すれば行列の 掛け算はできますが、内積を行うようなこうはできるのでしょうか。

  • ある行列とその転置行列の積の逆行列は?

    今エクセルで行列を使って問題を解いています。 問題は 行列X、A、Yがあり、Xは1行4列、Aは1行2列、Yは1行4列です。 X・A=Y という式があり、Aの行列は未知数a,bの要素からなっています。 X,Yはそれぞれ数値として要素が決まっています。 ここからはヒントとして表示されていました。 そこでXの逆行列を両辺の左からかけるとAは求まるはずですが、 Xは正方行列ではないので、Xの転置行列を左からかけます。 X(T)・Xは正方行列になるのでこれを行列Pとおくと Pの逆行列を求められ、右辺にP^-1をかけるとAが求まる。 というものです。 エクセルで書かれている通りにやってみて、エラーになるので調べてみると、XとXの転置行列の積の行列式は要素にかかわらず0になるようです。 実際に数値ではなく、abcdでやってみたところ0のようです。 この場合、逆行列は存在しないのではないかと思いますが、このヒントが間違っているとはあまり思えず、困っています。 補足ですが、この問題は最小二乗法をエクセルで行列を用いて行うという趣旨です。 もとのデータとして(x、y)の座標が4点与えられており、行列Xはxの要素を縦にならべたもの、Aは最小二乗法で求める一次関数式のパラメーターa,bで、YはXと同様座標のy要素です。 私の理解が間違っていて、何行何列という部分に誤りがあるなどの指摘があれば、ぜひお願いいたします。 そもそもある行列とその転置行列の積の逆行列は存在するのかどうかもお願いします。 締め切りが近く、ちょっとあせっています。 よろしくお願いします!!

  • フランク行列の逆行列を求める問題で質問です。

    フランク行列 a ij={ i (i≦j) 、 j (i>j) (iとjはaの添え字です) ただし、正方行列とする。 というものの逆行列を求めるもので、要素数がいくら大きくなっても書き換えが最小限で済むプログラムを作って、5×5行列のときにその逆行列を求めたいのですが、何回やっても思うようにいかずに、本当に困っています。どうか助けてください。お願いします。

  • 線形変換と表現行列

    少し長いですが、線形変換と表現行列についてです。 ------------------------------------------------ 平面のベクトル全体を V^2 として、V^2 の元a を、座標系Γに関して、方程式 g: 2x-3y+1=0, h: x+2y-3=0 で、gに沿ってhに平行射影する V^2 の線形変換Tの、Γの基本ベクトル{e1, e2}に関する行列(表現行列?)を求めよ --------------------------------------------------- という問題にて、 g の方向ベクトル a1=(3, 2) h の方向ベクトル a2=(-2, 1) として、 λa1 + μa2 = e1  ・・・(*) λ'a1 + μ'a2 = e2 ・・・(**) を解いて得た、μ, μ'を使って [ μa2 μ'a2 ] が求める行列だから・・・ と解説に書いてあるのですが、何故(*), (**) の式を立てるのかがわかりません。 線形変換である点と、自然基底である点から、 座標系Γの点 X=(x1, x2)を条件にしたがって平行射影し、h上にのっかた点を Y=(y1, y2)として Y = AX となるような線形変換のAを求めればいいのかな?なんて思っていたのですが・・・。 (表現行列は、基底が自然基底で、同じ線形部分空間への写像であれば、そういう風に求められるということが書いてあった気がしたので・・・) 第一、なんで直線h の切片 情報が使われていないかがわかりません^^; 問題をかなり変に解釈してしまっているのだと思いますが、これはどういうことなのでしょうか。 アドバイスをお願いします。

専門家に質問してみよう