FORTRAN功能

Saj*_*sad 6 recursion fortran function fortran95

我正在开发一个需要在FORTRAN中实现很少数值方法的项目.为此,我需要编写一些递归函数.这是我的代码.

!     
! File:   main.F95
!

RECURSIVE FUNCTION integrate(n) RESULT(rv)
    IMPLICIT NONE
    DOUBLE PRECISION :: rv
    INTEGER, INTENT(IN) :: n
    DOUBLE PRECISION, PARAMETER :: minusone = -1.0
    IF (n == 1) THEN
        rv = 10 !exp(minusone)
        RETURN
    ELSE
        rv = 1 - (n * integrate(n - 1))
        RETURN
    END IF
END FUNCTION integrate

RECURSIVE FUNCTION factorial(n) RESULT(res)
    INTEGER res, n
    IF (n .EQ. 0) THEN
        res = 1
    ELSE
        res = n * factorial(n - 1)
    END IF
END

PROGRAM main
    DOUBLE PRECISION :: rv1
    PRINT *, factorial(5)
    PRINT *, integrate(2)

    !READ *, rv1

END PROGRAM main
Run Code Online (Sandbox Code Playgroud)

对于此程序,输出为:

         NaN
       1
Run Code Online (Sandbox Code Playgroud)

如果我改变了打印语句的顺序(第30和31行),输出将是:

         1
-19.000000
Run Code Online (Sandbox Code Playgroud)

输出应该是(对于原始的打印语句顺序):

  120  
  -19 
Run Code Online (Sandbox Code Playgroud)

我从维基百科Fortran 95语言功能页面中获取了阶乘函数.我是FORTRAN的新手,我不知道我的代码有什么问题.请帮帮我们.

  • 编译器:gfortran 4.5.3与Cygwin
  • IDE:Netbeans 7.0.1
  • 平台:Windows 7

先感谢您.

M. *_* B. 10

正如其中一条评论所提到的,更好的解决方案是将子程序和函数放入模块中,然后使用主程序中的该模块.这将使调用者知道这些过程的接口 - 在Fortran术语中是"显式的".编译器不仅可以正确处理函数的类型,还可以检查调用中的参数与被调用者中的参数("伪参数")之间的类型一致性,以确保一致性.

如果您使用尽可能多的调试选项,编译器将帮助您找到错误.使用gfortran,尝试:-O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck = all -std = f2008 -pedantic -fbacktrace

module factorial_procs

   IMPLICIT NONE

contains

   RECURSIVE FUNCTION integrate(n) RESULT(rv)
       DOUBLE PRECISION :: rv
       INTEGER, INTENT(IN) :: n

       IF (n == 1) THEN
           rv = 10
           RETURN
       ELSE
           rv = 1 - (n * integrate(n - 1))
           RETURN
       END IF
   END FUNCTION integrate

   RECURSIVE FUNCTION factorial(n) RESULT(res)
       INTEGER res, n
       IF (n .EQ. 0) THEN
           res = 1
       ELSE
           res = n * factorial(n - 1)
       END IF
   END

end module factorial_procs

PROGRAM main

    use factorial_procs

    implicit none

    PRINT *, factorial(5)
    PRINT *, integrate(2)

END PROGRAM main
Run Code Online (Sandbox Code Playgroud)

您可能会发现只能使用常规整数通过直接乘法计算非常小的整数的阶乘.一个修复是使用更大的整数类型,例如,

integer, parameter :: BigInt_K = selected_int_kind (18)
Run Code Online (Sandbox Code Playgroud)

就像你可以现代化并使用selected_real_kind而不是Double Precision一样.

  • 感谢您使用"使用模块"提示,它帮助我解决了另一个问题. (2认同)

mil*_*cic 8

您的功能写得正确.问题出在主程序中,你没有明确地声明类型integratefactorial函数,所以你有隐式类型,在这种情况下factorial假定REALintegrate假设INTEGER.出于某种原因,您的编译器没有警告您类型不匹配.我做了:

$ gfortran recurs.f90 
recurs.f90:26.22:

    PRINT *, integrate(2)
                      1
Error: Return type mismatch of function 'integrate' at (1) (INTEGER(4)/REAL(8))
recurs.f90:27.22:

    PRINT *, factorial(5)
                      1
Error: Return type mismatch of function 'factorial' at (1) (REAL(4)/INTEGER(4))
Run Code Online (Sandbox Code Playgroud)

您应该将主程序更改为:

PROGRAM main
    IMPLICIT NONE
    DOUBLE PRECISION, EXTERNAL :: integrate
    INTEGER, EXTERNAL :: factorial
    PRINT *, factorial(5)
    PRINT *, integrate(2)
END PROGRAM main
Run Code Online (Sandbox Code Playgroud)

注意这IMPLICIT NONE条线.此声明语句将禁用任何隐式类型,如果未显式声明所有变量和函数,编译器将抛出错误.这是每个Fortran程序中非常重要的一行,如果你有它,你会自己弄清楚你的问题,因为它会强迫你明确地声明程序中的所有内容.

现在的输出是:

         120
  -19.0000000000000     
Run Code Online (Sandbox Code Playgroud)

正如所料.

作为边注,该DOUBLE PRECISION类型声明并不像使用如柔性REALKIND,而不是指定的参数,例如一个REAL(KIND=myRealKind).查看有关如何KIND正确使用的问题的答案:Fortran 90种参数.