• ベストアンサー

質問(Fortran)について

おはようございます。 下記のFortranでここから~ここまでと---で囲んでいる 部分の意味が分かりません。 乱数Pを発生させてPがEE以下になったら、140へ行けとあるのですが。。 それと(1)の部分をCに書き換えるとどうなるか、知っている方教えてください。 よろしくお願いいたします。 C *---------------------------------------------------------* C サブルーチンWGEN C *---------------------------------------------------------* SUBROUTINE WGEN(EM,R,NN,IR,ACC,ND,DT,AMAX,VMAX,MXCYCL,ERR,UW1, * UW2) C implicit real*8(a-h,o-z) COMPLEX*16 C(4096) DIMENSION ACC(ND),UW1(ND),UW2(ND) DIMENSION E(33),X(33),EE(33) DIMENSION PDIF(2046),PHI(2049),F(2049),T(2049),SV(2049),H(1), * RES(2049,1),RR(2049) PARAMETER (PI2=6.283185) DATA DX/0.03125/,H0/0./,H/0.05/,IR/101/ C C ------------------- ここから ------------------- DO 150 K=1,NN2-2 P=RAND2(IR) ← (1) C DO 130 J=2,33 IF(P.LE.EE(J)) GO TO 140 C 130 CONTINUE C 140 PDIF(K)=-(X(J-1)+(P-EE(J-1))/(EE(J)-EE(J-1))*DX)*PI2 C 150 CONTINUE C ------------------- ここまで ------------------- C *---------------------------------------------------------* C ファンクションRAND01 C *---------------------------------------------------------* REAL*8 FUNCTION RAND2(I) C INTEGER*4 L,C,T30 REAL MU PARAMETER(L=843314861,C=453816693,T30=2**30,MU=2.0**31) C I=L*I+C IF(I.LT.0) I=(I+T30)+T30 RAND2=REAL(I)/MU END C

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

  • ベストアンサー
  • info22
  • ベストアンサー率55% (2225/4034)
回答No.1

ファンクションRAND01(RAND2)の乗算剰余法で求めた0~1の間の乱数をPに代入、32個のEEと個々Pを比較しPがEEのどれは1つ以下となった時点で140にジャンプする。32このいずれのEEに対してもEE以下にならない場合は(1)のPをそのまま使って140に進むという内容です。DO 150で140で計算したPDIFを(NN2-3)個繰り返し計算しています。140の計算式が何をしているかわこのプログラムを見ただけでは分かりかねます。このサブルーチンWGENそのものの計算目的の計算式であることには違いないですが。 yamayama1さんがこのプログラムを提示されているわけですからこのサブルーチンが何をするものかわかって見えるでしょうから、140の式はそのための最終の式ですのでyamayama1さん自身はわかってみえると思います。 >それと(1)の部分をCに書き換えるとどうなるか、 乱数が得られなくなり、Pが未定義となるエラーが発生します。

その他の回答 (1)

  • nucomewl
  • ベストアンサー率25% (2/8)
回答No.2

f2c というプログラムでフォートランのソースはCに変えられます。 といってもgoto連発で読みやすいものではないようですが。。

関連するQ&A

  • FortranをCに書き直すにはどうしたらいいでしょうか?

    Foratranで書かれている下記のコードをCのコードに置き換えたいのですが、分かりません。 お願いします=(^v^)= C *---------------------------------------------------------* C サブルーチンWGEN C *---------------------------------------------------------* SUBROUTINE WGEN(EM,R,NN,IR,ACC,ND,DT,AMAX,VMAX,MXCYCL,ERR,UW1, * UW2) C implicit real*8(a-h,o-z) COMPLEX*16 C(4096) DIMENSION ACC(ND),UW1(ND),UW2(ND) DIMENSION E(33),X(33),EE(33) DIMENSION PDIF(2046),PHI(2049),F(2049),T(2049),SV(2049),H(1), * RES(2049,1),RR(2049) PARAMETER (PI2=6.283185) DATA DX/0.03125/,H0/0./,H/0.05/ C C DO 150 K=1,NN2-2 P=RAND2(IR) C DO 130 J=2,33 IF(P.LE.EE(J)) GO TO 140 C 130 CONTINUE C 140 PDIF(K)=-(X(J-1)+(P-EE(J-1))/(EE(J)-EE(J-1))*DX)*PI2 C 150 CONTINUE C C *---------------------------------------------------------* C ファンクションRAND01 C *---------------------------------------------------------* REAL*8 FUNCTION RAND2(I) C INTEGER*4 L,C,T30 REAL MU PARAMETER(L=843314861,C=453816693,T30=2**30,MU=2.0**31) C I=L*I+C IF(I.LT.0) I=(I+T30)+T30 RAND2=REAL(I)/MU END C

  • 【fortran】フーリエ級数について

    こんばんは。 早速ですが、質問させて頂きます。 学校の課題で一次元熱伝導方程式のプログラムを組みなさいという課題が出たのですが、入力、出力のプログラムが上手く書けずに困っています。 自分で何回もやってみたのですが、「ループがベクトル化されました」としか出ず、どこが間違っているのかも分からない状況です。 詳しい方、教えて頂ければ幸いです。 下に自分が作成したプログラムを載せておきます。 program heat implicit none integer i, n, nmax real(8) t0, t1, d, time, a, h, p, q, an0, kn, bn, en integer, parameter :: id = 100 real(8), parameter :: pi = 3.1415926535d0 real(8), parameter :: lambda = 2.5d-6, rho = 2500.d0, c = 2.35d-7 real(8), parameter :: expmax = 50.d0 real(8) x(0:id), t(0:id) ! ! Data input part (t0,t1,d,a,time,nmax) ! t0=300.0d0 ! degrees t1=200.0d0 ! degrees d =100.0d0 ! m time=1.0 ! year time = time *365.0d0*24.0d0 ! year --> hour nmax=1000 a = 1.0d6 ! Area of rock surface [m^2] h=d/id do i=0,id x(i)=i*h t(i)=t1 end do p=0.0d0 q=0.0d0 do n=1,nmax,2 an0=4.0d0/(n*pi)*(t0-t1) kn=n*pi/d bn=lambda*kn*kn/(rho*c) if(bn*time.le.expmax) then en=exp(-bn*time) else en=0.0d0 endif do i=0,id t(i)=t(1)+an0*sin(kn*x(i))*en enddo p=p+an0*kn*en q=q+an0*kn/bn*(1.0d0-en) enddo p=lambda*a*p q=lambda*a*q open(20,file=‘output.dat’) write(20,*) ‘x(i),t(i),p,q' = ‘, ‘x(i),t(i),p,q' close(20) stop end program heat

  • 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で・・・

    実行の画面に数字を入力すると、 英語の文章と 0.0 0.0 0.0 -NaN -NaN -NaN という文字が出てくるだけなんですが、これはプログラムが組めていないということなのでしょうか? ちなみに、打ったプログラムは、 C 判別関数 WRITE(*,100) 100 FORMAT(1H1/22X,'判別関数モデル'//19X,'消費量',3X,'消費比率'//19X, +'清酒',5X,'焼酎',5X,'ビール',7X,'清酒',6X,'ビール',7X,'M'10X,'D'/ +/) DO 10 I=1,47 CALL SUB1 10 CONTINUE STOP END SUBROUTINE SUB1 DIMENSION B1(3),B2(3),C(3),L(3),P(3) CHARACTER*12 A READ(5,50) A 50 FORMAT(3F8.1,3F7.1) X=1.0 DO 11 K=1,300 Y1=(-1.0) Y2=0.0 DO 12 J=1,3 B2=0.0 B1=0.0 L(J)=(-NINT(B1(J)*10.0/B2(J))) S1=Y1+X**L(J) S2=Y2+L(J)*X**(L(J)-1) Y1=S1 Y2=S2 12 CONTINUE W=X-Y1/Y2 IF(ABS(W-X).LT.1E-10) GO TO 13 X=W 11 CONTINUE 13 WO=W DO 14 J=1,3 C(J)=WO**L(J) 14 CONTINUE R1=0.0 DO 15 J=1,3 R2=R1+B2(J) R1=R2 15 CONTINUE D=0.0 DO 16 J=1,3 P(J)=B2(J)/R1 DO=D+P(J)*ALOG(P(J)/C(J)) D=DO 16 CONTINUE E=0.0 DO 17 J=1,3 EO=E+(B1(J)/B2(J)*P(J)) E=EO 17 CONTINUE WRITE(*,200) A,B2,P,E,D 200 FORMAT(1H,2X,A12,3X,3(F7.1,2X),4X,3(F9.6,X),4X,F9.6,2X,F9.6) RETURN END です。

  • FORTRAN…これってどんなプログラムになりますか??

    DO 10 I=1,47 CALL SUB1 10 CONTINUE STOP END SUBROUTINE SUB1 DIMENSION B1(3),B2(3),C(3),L(3),P(3) CHARACTER*12 A READ(5,50) A,B1,B2 50 FORMAT(A12,3F8.1,3F7.1) X=1.0 DO 11 K=1,300 Y1=(-1.0) Y2=0.0 DO 12 J=1,3 L(J)=(-NINT(B1(J)*10.0/B2(J))) Y1=Y1+X**L(J) Y2=Y2+L(J)*X**(L(J)-1) 12 CONTINUE W=X-Y1/Y2 IF(ABS(W-X).LT.1E-10) GO TO 13 X=W 11 CONTINUE 13 WO=W DO 14 J=1,3 C(J)=WO**L(J) 14 CONTINUE R1=0.0 DO 15 J=1,3 R2=R1+B2(J) R1=R2 15 CONTINUE D=0.0 DO 16 J=1,3 P(J)=B2(J)/R1 D=D+P(J)*ALOG(P(J)/C(J)) 16 CONTINUE E=0.0 DO 17 J=1,3 E=E+(B1(J)/B2(J)*P(J)) 17 CONTINUE WRITE(*,200) A,B2,P,E,D 200 FORMAT(1H,2X,A12,3X,3(F7.1,2X),4X,3(F9.6,X),4X,F9.6,2X,F9.6) RETURN END

  • fortran定数が代入されない

    fortran95で以下のような内部サブルーチンを作ったのですが、P(F)=1,2の定数がどこにも代入されません。どなたかfortan詳しい方、教えていただけると幸いです。 program sub_1028_1 real :: DU=10. real :: DIS1=2. real :: SL1=10. real,dimension(1:5) :: DEPTH real,dimension(2) :: P real,dimension(5,10) :: DR integer :: F real :: L P(1)=1 P(2)=2 OPEN(11, FILE='C:\Users\Documents\\FORTRAN\fortranopenfile\fortranresult.csv') CALL sub1(DEPTH) do F=1,2 write(11,*) P(F) do L=1.,SL1 DR(F,L)=(-1.0*P(F)+3.0)*DU*DEPTH(L)*0.1 write(11,'(F15.5)') DR(F,L) end do end do close(11) contains !----------------------------------------------------- SUBROUTINE sub1(DEPTH) real,dimension(1:5) :: DIS2,FE,DEPTH real,dimension(2,10) :: MTD integer :: F real :: L do F=1,2 write(11,*) P(F) do L=1.,SL1 DIS2(L)=DIS1*L FE(L)=DIS2(L)*0.1 DEPTH(L)=DIS2(L)*0.01 MTD(F,L)=(-1.0*P(F)+2.5)*FE(L) write(11,'(5F15.5)') DIS2(L), FE(L), DEPTH(L), MTD(F,L) end do end do end subroutine sub1 !---------------------------------------------------------- end program sub_1028_1

  • 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 -----------------------------

  • fortranのプログラムで困っています。

    implicit real*8(a-h,o-z) dimension h(10,300) h(1,g)=1.0d0 h(2,g)=g*2.0d0 open(6, file='testes-ex.f', status='replace') do 12 n=1,2 do 11 i=1,2 g=2.0d0*i 11 write(6,*) h(n,g) 12 write(6,*) stop end として出力させると値がすべて0になってしまいます。 私としては1.0 2.0  1.0 4.0 と出力させたいのですが、 どこに問題があるのでしょうか? 当方fortran初心者ですのですごく馬鹿げた質問をしているかも しれませんが…気付くことがあればご指摘よろしくお願いします。

  • FORTRAN→Cに翻訳

     どなたか、次のFORTRANのプログラムを、Cに、翻訳して頂けないでしょうか。C++ではなく、Cです。ANSI準拠のCでお願いします。  プログラムの内容は、最小二乗法による計算プログラムです。MS-DOS Ver3.3~6.0の頃の、MS FORTRANコンパイラ仕様のものです。その頃持っていたFORTRANの本も処分してしまい、今からFORTRANを学びなおすのにも多大な労力と時間がかかりそうなので、Cに翻訳して頂ければ大変ありがたいです。よろしくお願いします。 (“□”はタブ) ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ C□LEAST SQUARE APPROXIMATION □PROGRAM MAIN9 □DIMENSION X(100),Y(100),S(0:18),T(0:9),SM(10,10),TV(10),AV(10) □WRITE(*,*) 'N ?' □READ(*,*) N □WRITE(*,*) 'x1,x2,..,xn ?' □READ(*,*) ( X(I),I=1,N ) □WRITE(*,*) 'y1,y2,..,yn ?' □READ(*,*) ( Y(I),I=1,N ) □WRITE(*,*) 'M ?' □READ(*,*) M □DO 110 K=0,M*2 □□VS=0. □□DO 100 I=1,N □100□VS=VS+X(I)**K □□S(K)=VS □110□CONTINUE □□DO 130 K=0,M □□□VS=0. □□□DO 120 I=1,N □120□VS=VS+Y(I)*X(I)**K □□□T(K)=VS □130 CONTINUE □□DO 140 I=1,M+1 □□□DO 140 J=1,M+1 □□□□K=I+J-2 □□□□SM(I,J)=S(K) □140 CONTINUE □□DO 150 I=1,M+1 □150 TV(I)=T(I-1) □□CALL SIMULE( AV, SM, TV, M+1 ) □□DO 160 I=1,M+1 □160 WRITE(*,1000) I-1,AV(I) □1000 FORMAT(1H ,'A',I1,'=',F10.5) □□STOP □□END ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆

  • fprintfでの文字化け

    Cで作ったプログラムなのですが最後の部分でファイルに出力すると数字が 文字化けして出てきます(‰など)その原因を教えて頂ければ嬉しいです 他にも何かあれば教えてください プログラミングは詳しくないのでゴロゴロ見つかるかもしれません 【プログラム】 #include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> int a,i,j,k,t; double p,p1,b; int X[999][1000],Y[999][1000]; int s0,s1,delta; int main(void) { int**X = calloc(sizeof(int),sizeof(int)*1000); int**Y = calloc(sizeof(int),sizeof(int)*1000); FILE *output; output=fopen("monte.dat","w"); b = 0.01; /*逆温度*/ srand((unsigned int)time(0)); /*メモリの確保*/ if( X == NULL ){ exit( EXIT_FAILURE ); } for(i=0; i<=999; ++i){ /* 各列分の領域を割り当てる */ X[i] = (int*)calloc(sizeof(int),sizeof(int)*1000); } if( Y == NULL ){ exit( EXIT_FAILURE ); } for(i=0; i<=999; ++i){ /* 各列分の領域を割り当てる */ Y[i] = (int*)calloc(sizeof(int),sizeof(int)*1000); } /*終わり*/ /*初期配列の設定*/ for(i=0;i<1000;i++){ X[0][i]=a; a = (int)((rand() / ((double)RAND_MAX+1.0)) * 2);//debag } /*終わり*/ for(t=0;t<2;t++){ //debag /*配列中a番目を抽出*/ a = 10; //debag /*終わり*/ /*a番目のスピンを逆にした配列作成*/ for(j=0;j<1000;j++){ Y[t][j] = X[t][j]; } Y[t][a] = (X[t][a]+1)%2; /*終わり*/ /*遷移確率p1計算*/ s0=0; s1=0; for(k=0;k<1000;k++){ s0=s0+pow(-1,X[t][k]+X[t][k+1]);//(11),(00)なら値1 s1=s1+pow(-1,Y[t][k]+Y[t][k+1]);//(10),(01)なら値-1 } delta = -s1 + s0; p1 = 0.5 * (1 - tanh(0.5 * b * delta)); printf("%d %d %d %f ",s0,s1,delta,p1); //←この時点ではX[t][]は正しく出力する /*終わり*/ /*新しい配列(i番目の符号を交換するか)*/ p = (double)((rand() / ((double)RAND_MAX+1.0)) * 1); for(j=0;j<1000;j++){ X[t+1][j] = X[t][j]; } if(p<=p1){ X[t+1][a] = (X[t][a]+1)%2; printf("交換したよ! %d → %d\n",X[t][a],X[t+1][a]); } else{ X[t+1][a] = X[t][a]; printf("交換しないよ!\n"); } /*終わり*/ } /*記入*/ for(i=0;i<1000;i++){ fprintf(output,"%d ",X[0][i]); //←ここが文字化けする } fprintf(output,"\n"); for(i=0;i<1000;i++){ fprintf(output,"%d ",Y[0][i]); //←出力されない } /*終わり*/ fclose(output); return 0; } 【プログラム終】

専門家に質問してみよう