令人沮丧的代码给了我奇怪的输出,可能是由于WRITE和READ?

时间:2017-05-29 09:26:33

标签: integer fortran gfortran

这是一个较长的代码,我遇到了麻烦,我认为这是因为我不确定我是否完全理解行WRITE(6,*) 'INPUT S,K,TAU,SIGMA,R,DELTA,DTAU'READ(5,*) S,K,TAU,SIGMA,R,DELTA,DTAU。如果我只是运行.f文件,我得到

executable.exe INPUT S,K,TAU,SIGMA,R,DELTA,DTAU

然后我输入以下输入

100.0d0,100.0d0,3.0d0,0.2d0,0.08d0,0.04d0,0.03d0

执行此操作后,我在目录中获取一个名为“fort.2”的新文件。我不知道代码中的哪个据说可以生成?因为如果我改变

WRITE(2,10) T(I),BD(I) 

WRITE(3,10) T(I),BD(I)

我仍然得到文件“fort.2”。无论如何我怀疑“fort.2”是正确的输出,因为在其中有两列(1)T(I)的值和(2)BD(I)的值。第一列是正确的T(I)0.03d0步骤更改为3.0d0,这来自DTAU, TAU。但是BD(I)每个0.03d0步骤都不会发生变化,它会在几个0.03d0步骤中保持不变,然后会突然发生变化(如步进功能)。 BD(I)应该针对每个3.0d0步骤进行更改。现在我不知道我有点失落。主要代码:

      IMPLICIT NONE
      INTEGER MS,NS,JS,N,I
      PARAMETER(MS=50000,NS=50000)
      REAL*8 S,K,TAU,SIGMA,R,DELTA,SMIN,SMAX,DTAU,ALPHA,BETA,LAM
      REAL*8 V(0:MS),BD(0:NS),T(0:NS)
      COMMON/OUTPUT/V,BD,T

      WRITE(6,*) 'INPUT S,K,TAU,SIGMA,R,DELTA,DTAU'
      READ(5,*) S,K,TAU,SIGMA,R,DELTA,DTAU

      N = TAU/DTAU
      ALPHA = 2.0D0*R/SIGMA**2
      BETA = 2.0D0*(R-DELTA)/SIGMA**2
      LAM = (BETA-1.0D0) + DSQRT((BETA-1.0D0)**2+4.0D0*ALPHA)
      LAM = LAM/2.0D0
      SMIN = K/(1.0D0+1.0D0/LAM)               ! PERPETUAL BOUNDARY
      SMAX = 10.0D0*K
      CALL EXP_DIFF(S,K,TAU,SIGMA,R,DELTA,SMAX,SMIN,DTAU,JS)

      WRITE(6,*) 'PRICE: ', V(JS)
      DO I = 0, N
       WRITE(2,10) T(I),BD(I)
      ENDDO
10    FORMAT(1X,2F14.8)

      STOP
      END


C=======================================================================
      SUBROUTINE EXP_DIFF(S,K,TAU,SIGMA,R,DELTA,SMAX,SMIN,DTAU,JS)
      IMPLICIT NONE
      INTEGER MS,NS,JS,M,N,I,J,IEARLY
      PARAMETER(MS=50000,NS=50000)
      REAL*8 S,K,TAU,SIGMA,R,DELTA,XMIN,XMAX,DTAU,DX,ALPHA,SMIN,SMAX,
     &       P1,P2,P3,VC,A,B
      REAL*8 VE(0:MS),V(0:MS),BD(0:NS),T(0:NS)
      COMMON/OUTPUT/V,BD,T

      IF (S.GT.SMAX) THEN
       STOP 'THE OPTION IS WORHTLESS'
      ENDIF

      IF (S.LT.SMIN) THEN
       STOP 'THE OPTION WORTHS K-S FOR CERTAIN'
      ENDIF

      XMIN = DLOG(SMIN)
      XMAX = DLOG(SMAX)
      DX = SIGMA*DSQRT(3.0*DTAU) 
      JS = (DLOG(S)-XMIN)/DX
      DX = (DLOG(S)-XMIN)/FLOAT(JS)
      ALPHA = R - DELTA - SIGMA**2/2.0
      P1 = SIGMA**2*DTAU/(2.0*DX**2) + ALPHA*DTAU/(2.0*DX)
      P2 = 1.0 - SIGMA**2*DTAU/DX**2
      P3 = 1.0 - P1 -P2
      P1 = P1/(1.0+R*DTAU)
      P2 = P2/(1.0+R*DTAU)
      P3 = P3/(1.0+R*DTAU)
      WRITE(6,*) 'P1,P2,P3',P1,P2,P3
      IF (P1.LT.0.0.OR.P2.LT.0.0.OR.P3.LT.0.0) STOP 'DECREASE DTAU'

      M = (XMAX-XMIN)/DX
      N = TAU/DTAU
      IF (M.GT.MS.OR.N.GT.NS) STOP 'INCREASE MS AND NS'
      DO J = 0, M
       VE(J) = MAX(K-DEXP(J*DX+XMIN),0.0)
       V(J) = VE(J)
      ENDDO

      BD(0) = K
      T(0) = 0.0      
      DO I = 1, N
       IEARLY = 0
       A = V(M)
       B = V(M-1)
       DO J = M-1, 1, -1
        VC = P1*A+P2*B+P3*V(J-1)
        IF (VC.LT.VE(J).AND.IEARLY.EQ.0) THEN
         BD(I) = DEXP(XMIN+J*DX)
         T(I) = DTAU*DFLOAT(I)
         IEARLY = 1
        ENDIF
        V(J) = MAX(VC, VE(J))
        A = B
        B = V(J-1)
       ENDDO
      ENDDO

      RETURN
      END

2 个答案:

答案 0 :(得分:1)

在程序中,行

WRITE(6,*) 'INPUT S,K,TAU,SIGMA,R,DELTA,DTAU' 

应该向用户写出指令。在那之后,行

READ(5,*) S,K,TAU,SIGMA,R,DELTA,DTAU

等待以RETURN结尾的逗号分隔值列表。所以我猜这是预期的行为。如果您运行该程序,当您看到输出

INPUT S,K,TAU,SIGMA,R,DELTA,DTAU

输入7,以逗号分隔的值,程序将为您计算结果。

另一方面,如果您将原始WRITE声明更改为

WRITE(6,*) S,K,TAU,SIGMA,R,DELTA,DTAU

你会得到一些随机输出,因为那些你正在写出来的值的变量在那时是未初始化的。

修改

许多网页都详细解释了WRITE格式。请参阅示例this one。在您的具体情况下,有WRITE行和FORMAT行,它们一起指定输出的外观:

      WRITE(2,10) T(I),BD(I)
      ...
10    FORMAT(1X,2F14.8)

WRITE(2,10) T(I),BD(I)将变量写入文件流2(您最有可能使用open (unit = 2, file = "fort.2")之类的命令打开这些变量,其格式为10行指定的格式(这只是写声明下面的两行)。格式说明符的工作原理在我提供的链接中有解释。

编辑2

正如评论中所指出的,fort.2是一些fortran编译器使用的标准名称,如果写入流nr。 2没有先使用OPEN语句。如果您想确保代码正常工作并自己设置文件名,请使用

OPEN(UNIT=2, FILE='myfile.txt')

答案 1 :(得分:0)

BD(I)正在逐步改变,因为它的计算是在这个IF测试中:

    IF (VC.LT.VE(J).AND.IEARLY.EQ.0) THEN
       BD(I) = DEXP(XMIN+J*DX)
       T(I) = DTAU*DFLOAT(I)
       IEARLY = 1
    ENDIF

从I = 1到I = 10,当J = 3时,IF测试成功。当I = 11时,当J = 2时成功,改变BD(I)的计算。当I = 38时,IF测试在J = 1时成功,BD(I)的计算再次改变。