• 締切済み

fortranを用いた行列の掛け算について

行列の掛け算についてなのですが、ある行列aを2乗した行列bを求める場合は以下のようなプログラムを書けば出来たのですが、これを3乗以上に拡張するためにはどうしたらよいのでしょうか? ______do i=1,3 ________do j=1,3 __________b(i,j)=0.D0 ____________do k=1,3 ______________b(i,j)=b(i,j)+a(i,k)*a(k,j) ____________enddo ________enddo ______enddo

みんなの回答

回答No.1

program hello implicit none real,allocatable,dimension(:,:):: d real,allocatable,dimension(:,:):: x integer::i allocate(d(3,3)) allocate(x(3,3)) d(1,1) = 5 d(1,2) = 4 d(1,3) = 4 d(2,1) = 7 d(2,2) = 2 d(2,3) = 4 d(3,1) = 7 d(3,2) = 6 d(3,3) = 2 x = mpow(d,3); do i = 1,ubound(x,2) print *, x(i,:) end do contains function mmulti(x,y) real,intent(in),allocatable,dimension(:,:)::x real,intent(in),allocatable,dimension(:,:)::y real,allocatable,dimension(:,:)::mmulti integer::i integer::j integer::k allocate(mmulti(ubound(x,1),ubound(y,2))) do i = 1,ubound(x,1) do j = 1,ubound(y,2) mmulti(i,j) = 0 do k = 1,ubound(x,2) mmulti(i,j) = mmulti(i,j) + x(i,k) * y(k,j) end do end do end do end function mmulti function mpow(x,n) real,intent(in),allocatable,dimension(:,:)::x integer,intent(in)::n real,allocatable,dimension(:,:)::mpow integer::i allocate(mpow(ubound(x,1),ubound(x,1))) mpow = x do i = 1,n - 1 mpow = mmulti(mpow,x); end do end function mpow end program hello 全部書いてみた。g95でコンパイルして 1077. 692. 620. 1085. 684. 620. 1211. 804. 684. の結果を得て、Excelとの一致も確認しました。 表示用のサブルーチンに分けようとしてうまくいかなかったり、 n乗で与えられるnが負でないときや 与えられた二つの行列x,yについて,xの行数とyの列数が等しくないときや xが正方行列でないときに エラー出さないといけないんですが, 方法をすぐに調べられなかったので断念しました。

関連するQ&A

  • fortran 行列ベクトル積

    行列ベクトル積を計算するプログラムを下のように書いたのですが、実行した結果の答えが実際計算した答えと異なります。初期の要素の設定がおかしいのでしょうか?教えて下さい。よろしくお願いします。 program list2_14 implicit none integer , parameter :: n = 2 real(8) a(n,n), x(n), y(n) integer i, j, k, l a(1,1:2) = (/1.2d0,3.4d0/) a(2,1:2) = (/5.6d0,7.8d0/) x(:) = (/9.0d0,10.0d0/) do i = 1, n y(i) = 0.0d0 do j = 1, n y(i) = y(i) + a(i,j) * x(j) enddo enddo do k = 1, n write(*,*) (a(k,l), l = 1, n) enddo write(*,*) x(:) write(*,*) y(n) end program list2_14 実行結果 1.2 3.4 5.6 7.8 9. 10. 128.4

  • fortran 上三角行列

    一様乱数を要素とする上三角行列を設定するプログラミングを行ったのですが以下のプログラムで call random_number(a(1 : j , j)) a(j+1 : n , j ) = 0.0d0 の部分を理解した上で実行したのですが、実行結果がそれぞれの列に同じ一様乱数が表示されました。プログラム内容と実行結果が納得のいく物ではないのですが、果たして以下のプログラムは上三角行列を設定する正しく実行される物となっているのでしょうか?教えて下さい。よろしくお願いします。 program list2_8 implicit none real(8), allocatable :: a(:,:) integer n, i, j write(*,'(a)', advance ='no') ' input n (1<=n<=100) :' read(*,*) n if (n < 1 .or. 100 < n) stop 'stop, n is invalid' allocate (a(n,n)) call random_seed do j = 1, n call random_number(a(1:j,j)) a(j+1:n,j) =0.0d0 enddo do i = 1, n write(*,'(100e12.4)') a(1, 1:n) enddo end program list2_8

  • 行列の掛け算

    こんにちは。 今回のプログラムは4×4の行列と1×4の行列を掛け合わせて、 その結果を出力するというものです。 読み込むデータはdata[l][j]で 中身は 1 2 3 4 5 2 3 4 5 1 3 1 4 5 6 2 3 1 9 7 といった形になっています。 最初の 1 2 3 4 2 3 4 5 3 1 4 5 2 3 1 9 が4×4の行列になっていて、それに 4 5 5 9 を掛け合わせるというものです。その結果を まずx[0][j]にいれ、その結果と 1 2 3 4 2 3 4 5 3 1 4 5 2 3 1 9 をもう一度掛け合わせその結果を x[1][j]にいれ、 x[k][j]を出力するというプログラムです。 行列の掛け算の部分のプログラムは以下の通りです。 sprintf(fname,"impulse[%d].txt",c); fp = fopen(fname,"a"); for(k=0;k<2;k++){ for(j=0;j<4;j++){ for(l=0;l<4;l++){ x[k][j] +=data[l][j] * data[5][l]; data[5][l] = x[k][j]; fprintf(fp,"%8.8f\n",x[k][j]); } } } fclose(fp); です。これだと結果がすべて0となって出力されてしまいます。どこがいけないのでしょうか。

  • マクロの行列の掛け算ができません

    エクセルでマクロ勉強中の初心者です。 マクロで行列A(3行4列)、行列B(4行2列)の掛け算のプログラム(下記)を作っているのですが 「インデックスが有効範囲にありません」というエラーメッセージが出てしまいます。 エクセルで関数(MMULT)で同様の計算をするときちんと計算できるのですが・・・。 どなたか教えてください。 よろしくお願いいたします。 Sub s1() ' 次元の設定 Dim A(3, 4), B(4, 2), C(3, 2) N1 = 3: N2 = 4: N3 = 3 ' データの入力 (行列AとBの設定) For I = 1 To N1: For J = 1 To N2 A(I, J) = Worksheets("s1").Cells(I, J) Next J: Next I For I = 1 To N2: For J = 1 To N3 B(I, J) = Worksheets("s1").Cells(I, J + 5) Next J: Next I ' ベクトルの内積 For I = 1 To N1 For J = 1 To N3 For K = 1 To N2 C(I, J) = C(I, J) + A(I, K) * B(K, J) Next K Next J Next I ' 結果の出力 For I = 1 To N1 For J = 1 To N3 Worksheets("s1").Cells(I + 6, J + 7) = C(I, J) Next J Next I End Sub

  • fortran 配列受け渡し時の次元の一致

    fortran90、コンパイラはifortです。 普通メインプログラムとサブルーチン間での配列の受け渡しは、次元を揃えて渡すと思います。 とあるコード(以後コードA)を読んでいると、2次元配列を渡し、1次元配列で受け取っていました。 例 program test1 integer :: a(3,3) call testsub(a) end program subroutine testsub(b) integer :: b(9) end subroutine これが受け取り側でどう処理されているのかわからず、調べるために適当なテストコードを書きました。 a 123 456 789 ↓ b 123456789 になるとか 結果、コンパイルは通ったのですがサブルーチン側では全て0で置き換えられてしまいました。 コードAはpgiかなんかでコンパイルしていたようなのでコンパイラの違いでしょうか? よくわらなかったので質問させて頂きました。 質問をまとめますと、 (1)次元の異なる配列の受け渡しができるかどうか (2)その場合中身はどうなるか よろしくお願いします。 ---以下テストコード--- program testa implicit none integer :: a(3,3),i,j do i=1,3 do j=1,3 a(i,j)=j+(i-1)*3 enddo enddo do i=1,3 do j=1,3 write(6,*) a(i,j) enddo enddo call sub1(a) end program subroutine sub1(b) integer :: b(9),i do j=1,9 write(6,*) b(i),'sub' enddo end subroutine

  • Fortranの問題3問目です。急いでます><

    以下のプログラムを実行すると結果がNAN(数値エラー)となり、表示されない。 これは、ガウスの消去法における、ある問題に起因する。 正しい結果がでるようにするには、どうしたらよいか? 答えが正しく表示されない原因を究明し、正しい結果を表示する、 修正済みソースコードを提出しなさい。 ヒント: 一般に、どのような行列でも計算できるプログラムにするためには、 「ピボット」と呼ばれる操作を行う必要があるが、 今回は、ピボットをあらかじめ人間が行うことで回避してよい. プログラムの処理内容(アルゴリズム)を修正する必要はない。 program gauss implicit none c aは係数行列(4x3)、xは解、w は一時変数 double precision a(5,4),x(4),w integer i,j,k c キーボードから読み込む場合 write(6,*) 'input a(5,4)' c read(5,*) a c data文で一括初期化(代入)する方法 data a / & 0d0, 3d0, 7d0, 2d0, 65d0, & 2d0, 8d0, 5d0, 1d0, 65.4d0, & 5d0, 3d0,-5d0, 2d0, 3.8d0, & -2d0, 4d0, 0d0, -6d0, -35.6d0 & / write(6,*) 'データの確認表示' write(6,'(f8.2,f8.2,f8.2,f8.2,f8.2)') a c 前進消去 do k=1,3 do j=k+1,4 w = -a(k,j)/a(k,k) write(6,*) w,'*行',k,'を、行',j,'に足すと' do i=1,5 a(i,j) = a(i,j) + w*a(i,k) end do write(6,'(f8.2,f8.2,f8.2,f8.2,f8.2)') a write(6,*) '' end do end do write(6,*) '前進消去 終了' write(6,'(f8.2,f8.2,f8.2,f8.2,f8.2)') a c 後退代入 do k=4,1,-1 x(k) = a(5,k) do i=k+1,4 c 注:k=3のとき, do i=4,3 となるためループ内は1回も実行しない c k=2のとき, do i=3,3 となり、ループ内はi=3 で1回だけ実行 x(k) = x(k) - a(i,k)*x(i) end do x(k) = x(k) / a(k,k) end do c 解を表示 write(6,*) 'x = ',x stop end

  • FORTRAN 初心者です

    以下の連立一次方程式をSOR法で解く問題です。 初心者なりにガウスザイデル法を応用してプログラムしたつもりですが、やはり難しいです(答えは違います)。 どこをどうすれば良いのか分かりませんので、よろしければヒントや助言をいただきたいです。 PROGRAM SOR REAL A(10,10),B(10),X(10),X0(10) INTEGER N,I,J,K,Kmax,w N=3 A(1,1)=4 ;A(1,2)=1 ;A(1,3)=2 A(2,1)=1 ;A(2,2)=3 ;A(2,3)=1 A(3,1)=1 ;A(3,2)=2 ;A(3,3)=5 B(1)=16 B(2)=10 B(3)=12 X0(1)=1 ;X0(2)=1 ;X0(3)=2 w=1.2 Kmax=50 EPS=1.D-5 DO I=1,N D=A(I,I) S=B(I) B(I)=B(I)/D END DO DO K=1,Kmax DO I=1,N DO J=1,N if(J<I) X0(J)=X(J) S=S-A(I,J)*X0(J) END DO X(I)=(1-w)*X(I)+w*S END DO DO I=1,N S=S-(X(I)-X0(I))**2 END DO IF(S<EPS) GOTO 10 DO I=1,N X0(I)=X(I) END DO END DO 10 WRITE(*,*) K DO I=1,N WRITE(*,*) 'SOR法で求めた解は' WRITE(*,*) 'X(',I,')=',X(I) END DO END PROGRAM SOR !------------------------------------ ※wは緩和係数です

  • 院試の問題(FORTRAN)で。

    FORTRANを昨日勉強し始めたばかりの初心者です。 とある大学院の試験問題でわからない部分があるので質問させていただきます。 問題文とソースは以下のとおりです。 以下のFORTRANプログラムについて、標準出力への出力を答えよ。 program main intger :: m(3,3),i,j,k,n n=3 m(1,1)=2; m(1,2)=1; m(1,3)=2 m(2,1)=2; m(2,2)=3; m(2,3)=12 m(3,1)=8; m(3,2)=-6; m(3,3)=2 do i=1,n-1 do j=i+1,n m(j,i)=m(j,i)/m(i,i) ← do k=i+1,n m(j,k)=m(j,k)-m(j,i)*m(i,k) enddo enddo enddo write(6,*) m(2,1),m(2,3),m(3,2),m(3,3) end これを計算していくとm(2,2)=0(計算ミスだったらすみません)となってしまって 上のソースの矢印の部分でエラーが出てしまうと思い、 それだと出力出来ないのではないかと思ったんですが、 それでは答えにならないので質問させていただきました。 コンパイラを使って実行してみたいのもやまやまなんですが、 なにしろ試験まで時間があまりないもので・・・ どなたか回答できる方いらっしゃいましたらよろしくお願いします!

  • 2×2行列の掛け算をするプログラム

    タイトルのプログラムなんですが、授業で例題としてソース渡されたんですが、学校のUNIXのやつだと動くんですけど、自分の使ってるVC++だと動かないんですよ。 その理由と、VC++で動くようにするにはどうしたらいいかおしえてください。 ソースは、 #include<stdio.h> void get_data(); void write_data(); void product(); main() { double a[2][2],b[2][2],c[2][2]; get_data(a); get_data(b); write_data(a); write_data(b); product(a,b,c); write_data(c); } void get_data(double p[][2]) { int i,j; printf("Input elements\n"); for(i=0;i<2;i++) for(j=0;j<2;j++){ printf("(%d,%d)-th element=",i,j); scanf("%lf",&p[i][j]); } } void write_data(double p[][2]) { int i,j; printf("\n"); for(i=0;i<2;i++){ for(j=0;j<2;j++) printf("(%d,%d)-th element=%lf\t",i,j,p[i][j]); printf("\n"); } printf("\n"); } void product(double u[][2],double v[][2],double w[][2]) { int i,j,k; for(i=0;i<2;i++) for(j=0;j<2;j++){ w[i][j]=0.0; for(k=0;k<2;k++) w[i][j]+=u[i][k]*v[k][j]; } } です。 よろしくおねがいします。

  • 転置行列 証明 行列の積

    転置行列の証明について疑問点があるので 質問させて頂きます。 t(AB)=t(B)t(A) の証明について。以下に示します。 行列 A の (i,j) 成分を A[i,j] と書くことにします。 行列Bも同様。 (t(AB))[i,j] = (AB)[j,i] = Σ A[j,k] B[k,i] = Σ (tA)[k,j] (tB)[i,k]  …(1) = Σ (tB)[i,k] (tA)[k,j]  …(2) = ((tB)(tA))[i,j] よって、 t(AB) = (tB)(tA) (1)についてよくわかりません。 行列の積は、 (l,m)行列と(m,n)行列の積は(l,n)行列と定義されますが (1)は(m,l)行列と(n,m)行列の積を計算することに ならないのでしょうか? (m,l)行列と(n,m)行列の積は定義されないので等式でつないでは いけないのでは?と考えた次第です。 以上、ご指摘、ご回答よろしくお願い致します。

専門家に質問してみよう