• 締切済み

FORTRAN95でハフモデルの計算をしようと思っています。

FORTRAN95でハフモデルの計算をしようと思っています。 ハフモデルをちょっと拡張して計算を行いたく、なかなかプログラムを組めていません。 一番苦戦しているのが、配列に数字を入れる方法です。 縦5、横9からなる配列Bを定義して、(Bの左上の要素はB11とします) 1列目の2~5行目に1~4の数字を入れ, 1行目の2列目から後ろには1~9を入れて、Bを表示したいです。 ほかの要素は実数なのでBは実数型で定義します。 Bの完成イメージとしては 0 1 2 3 4 5 6 7 8 9 1 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 です。スペース部分はコンマですが。 プログラムを REAL,DIMENSION(5,9)::B B=0 DO I4=1,4 B(2:5,1)=I4 DO IXW=10,80,10 XWEI=REAL(IXW)/10.0 B(1,2:9)=XWEI END DO END DO DO I5=1,5 WRITE(*,100) (B(I5,J5),J5=1,9) 100 FORMAT(20(',',F3.1)) END DO STOP END こうかくと、 ,0.0,8.0,8.0,8.0,8.0,8.0,8.0,8.0,8.0, ,4.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, ,4.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, ,4.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, ,4.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, のように表示されます。DO文の対になるEND DOよりしたではDOの最後の値しか使えないようです。 しかし、WRITE文をEND DOより中に入れると5×9ではなくもっと縦長の15×9のような配列が表示されてしまいます。 どなたか教えてください。お願いします。

みんなの回答

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

人に聞くだけじゃなくって, 自分で考えるとか自力で調べるとかしてください. 少なくとも, forall を使う方は想像できるでしょ? もう一方も「なぜ i が 2回出てくるのか」を考えればそれなりに思い付くんではないかな.

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

「なぜそうなるのか」は自分できちんと調べてくださいとうち捨ててっと. Fortran95 だったら, わざわざ do をこんな風に使わなくてもいいじゃないの? B = 0 B(2:5, 1) = (/ (i, i=1, 4) /) B(1, 2:9) = (/ (i, i=1, 8) /) なり B = 0 forall(i=2:5) B(i, 1) = i-1 forall(i=2:9) B(1, i) = i-1 なりで終わってると思う. ああ, サイズが間違ってないか?

made_in_cue
質問者

補足

回答ありがとうございます。 シンプルに書く事ができました。 なぜDOを使ったかは、FORTRAN77の資料が多かったためです。便利な方法を知りませんでした。 次に横方向を0.5,1.0,1.5,と実数にしたいのですが、どうしたら良いのでしょうか? よろしくお願いします。

関連するQ&A

  • fortran allocateを使って配列宣言を

    今変数 aについて考えています.aは i,jの2次元の座標におけるデータです. a(1,1)は10個配列を持ちたい a(1,2)は5配列を持ちたい a(i,j)はn個配列を持ちたい このような場合どのように配列を定義すれば良いのでしょうか? 例えば 2次元の大きさが3x3の場合で,それぞれの位置に配列したいデータ個数をnとします. nには既に個数が定義されているとします.このとき aの配列は nを使ってどのように定義すれば良いのでしょうか? integer n(3,3) integer i,j real, allocatable :: a(:,:,:) do j=1,3 do i=1,3 n(i,j)=i*j end do end do do j=1,3 do i=1,3 allocate (a(n(i,j),3,3)) end do end do では aの宣言が重複するためエラーになってします. 何方か良い方法を教えて下さい.

  • FORTRAN subroutineと配列と繰り返し

     以下のように二次元配列の場合でsubroutineを使うときに、主プログラムで2重Doループ(iとj)で繰り返しをしているのですが、すでにsubroutineでDoループ(i)を用いて計算しています。これではsubroutineの利点をうまく使えていないと思うのですが、subroutineを使って配列、Doループをきれいにする方法をどなたか教えていただけませんか。  実際は4重ループ、4次元配列なので、プログラムをわかりやすくするためにサブルーチンを使いたいと思っています。 -------------------------------------------------------------- program S real,dimension(5,5) :: B real,dimension(5) :: A integer :: i,j do j=1,5 CALL sub1(A) do i=1,3 B(i,j)=A(i)*j write(*,*) B(i,j) end do end do end program S subroutine sub1(A) real,dimension(5) :: A integer :: i do i=1,3 A(i)=3.*i end do end subroutine sub1

  • FORTRANの動的割り当てについて

    今、FORTRANでg95でプログラムを作っているのですが、動的割り当てで理解出来ない現象が起きたので質問させていただきます。 real(8),dimension(:,:,:),allocatable :: a と三次元の動的配列aを定義し allocate(a(0:10,0:10,0:10)) としています。 ここで、外部のファイルから各成分0~10の配列の所に値を読み込ませます。 私の理解では、これは0~10の添字までしか扱えないものと思っていたのですが、write文でa(11,11,11)という要素を書かせてみると、実際に値が出力されてしまいます。動的割り当てとはそういうものなのでしょうか。 また現在作っているプログラムではこれが値を持っているとまずいので、doループで11の値のところだけをif文で0にしようと試みたのですが、そのif文を反映してくれません。 (つまり do i=0.11 do j=0,11 do k=0,11 if (i==11.or.j==11.or.k==11) then .・・・ の時、・・・のところで0にしようしてもそれが反映されない) 始めはコードが間違っているのかと思いましたが、doループの10の値のところを同様に0にしてみたら成り立っていました。 (つまり do i=0,10 do j=0,10 do k=0,10 if (i==10.or.j==10.or.k==10) then ・・・ の時、・・・のところで0にしようとするとそれが反映される) これはやはり定義してないa(11,11,11)が出力されることと関係があるのでしょうか。 初歩的な質問かもしれませんが、よろしくお願い致します。

  • Fortranの倍精度実数について

    こんにちは。 現在、Fortran 90でプログラムを作成しています。 その中で、整数の倍精度実数への型変換についての疑問がわきましたので、質問させていただきます。 以下の2つのプログラムで、計算がより速く、より精度よくできるのはAとBどちらなのでしょうか。 実際は下記のプログラムが、ループの中に入っているので少しでも計算時間を短くしたいのです。 よろしくお願いいたします。 program A(毎回dxを足す) ----------------------------- real(8) :: pi, dx real(8), dimension(1000) :: x integer i, j pi=atan(1d0)*4d0 dx=pi/5000d0 x=0d0 j=1 do i=1, 1000 x(i)=x(j)+dx j=i write(*,*)x(i) end do ----------------------------- program B(毎回dx*ループ回数を計算する) ----------------------------- real(8) :: pi, dx real(8), dimension(1000) :: x integer i, j pi=atan(1d0)*4d0 dx=pi/5000d0 x=0d0 do i=1, 1000 x(i)=dx*dble(i) write(*,*)x(i) end do -----------------------------

  • 行列の計算

    2行3列のマトリクスAと3行2列のマトリクスBの各要素(整数)をキーボードから読み込み、 C=A×BとなるマトリクスCを計算するプログラムを作りたい。 ただ、配列を使用せずに読み込み・計算・出力で作らなくてはなりません。 (まだ配列の勉強をしていないので…)    a11 a12 A= a21 a22    A31 a32    b11 b12 b13 B= b21 b22 b23 C=? 参考書などで調べたところ int main( void ) { int i, j; double a[3][3] = { { 1, 2, 1 }, { 3, 4, 3 }, { 1, 2, 1 } }; double b[3][3] = { { 1, 2, 3 }, { 1, 1, 1 }, { 3, 2, 1 } }; double c[3][3]; for( i = 0 ; i < 3 ; i++ ){ for( j = 0 ; j < 3 ; j++ ){ c[i][j] = a[i][j] + b[i][j]; } } } のようなものがでてきました。 数字を変え、+を*にしてやってみたのですが、うまくいきませんでした。 また、a11のような数字は認識しませんでした。 プログラム初心者で理解するのに時間がかかるかもしれませんが、 どなたかアドバイスお願いします。

  • FortranにあってCにない関数?について

    10年間Fortran90でプログラミングをしてきましたが、 C言語を使う必要があって、プログラムを書き直し中の者です。 入門書を数冊読んでいて疑問に思ったのですが、Fortranには、 A=SUM(B) と書けば、配列Bの全ての総和をAに返す、という関数があるのですが、C言語に同じような関数はないのでしょうか?(標準ライブラリに無いという事はないのでしょうか?) Fortranと比べてCは組み込み関数が少ないという印象を持ったのですが実際そうなのでしょうか? また、Fortanでは配列の和をとる時、 do i=0,n a(i)=b(i)+c(i) end do を一行で、 a(0:n)=b(0:n)+c(0:n) と書いても良いですし、もし定義されている全部の配列の要素が対象なら a=b+c と一行で書いても良いのですが、c言語では似たような書き方はできないのでしょうか? つまり、多次元配列を扱う時、Fortranでは単に「a=b+c」と書けば済むところを、Cでは for (i=0,i<=n,i++){ for (j=0,j<=n,j++){ for (k=0,k<=n,k++){ a[i][j][k]=b[i][j][k]+c[i][j][k]; }}} と書かなくてはいけないのか?と悩んでおります。 私がCの機能を知らないだけなのか、Cとはそうゆうことが出来ないのか、浅学なため判断できません。 ご教授ください、どうぞよろしくお願いいたします。

  • Fortranについて質問です。

    プログラムソースの中で ----------------------- Real*8 A(10,10) Do 30 i = 1, 5 Do 40 j = 1,5 A(i,j)=0.0D0 40 Continue 30 Continue ------------------------ というのは、 配列A(i,j)にどんな値を入れるのですか? すべて0が入るということですか? 教えてください><

  • fortran 途中まで考えたのですが。。。。

    エラトステネスのふるい(素数の倍数を除いていって残ったのが素数)で3桁の素数を求めて表示したいです。 私が考えたのは、 1・2~99までの数を素数かどうか調べて、素数を配列に入れていく 2・100~999まで素数の配列の中の数で割って、割り切れたらおしまい。割り切れなかったら表示していく ということです。 しかし下のプログラムではうまく素数配列ができていないようなのです。 ここまでかなり時間がかかったのでこのプログラムに手をいれて これ以外におかしくなるところもどこを直せばいいのか教えてくださるとうれしいです。 C C q223.f C PROGRAM q223 C IMPLICIT NONE C INTEGER N,i,K,s,l REAL a(99),b(99),c(99),X,Y C real M C a(1)=2 a(2)=3 l=2 C DO N=2,99,1 M=N**(0.5) S=M DO i=2,S,1 K=MOD(N,i) IF(K ==0)THEN exit ELSE IF(K /=0)THEN l=l+1 a(l)=N ENDIF ENDDO ENDDO C do N=100,999 do l=1,99 X=a(l) Y=N/X if(Y==0)then exit else if(Y/=0)then write(*,*)N end if end do end do c end よろしくおねがいします

  • 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は緩和係数です