我正在一个需要在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
对于此程序,输出为:
NaN
1
如果我更改打印语句的顺序(第30和31行),输出将是:
1
-19.000000
输出应为(对于原始打印对帐单顺序:]
120
-19
我从Wikipedia Fortran 95 language features页面上使用了阶乘函数。
您的函数编写正确。问题出在主程序中,在这里您没有显式声明integrate
和factorial
函数的类型,因此您具有隐式类型,在这种情况下,假定factorial
被假定为REAL
,而假定integrate
被确定为[ C0]。由于某种原因,您的编译器没有警告您有关类型不匹配的信息。我的做了:
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))
注意PROGRAM main
IMPLICIT NONE
DOUBLE PRECISION, EXTERNAL :: integrate
INTEGER, EXTERNAL :: factorial
PRINT *, factorial(5)
PRINT *, integrate(2)
END PROGRAM main
行。该声明语句将禁用任何隐式类型,并且如果未明确声明所有变量和函数,则编译器将引发错误。这是每个Fortran程序中非常重要的一行,如果有的话,您会自己解决问题,因为这将迫使您在程序中显式声明所有内容。
现在的输出是:
IMPLICIT NONE
按预期。
作为旁注, 120
-19.0000000000000
类型声明不如使用指定了DOUBLE PRECISION
参数的REAL
灵活,例如an KIND
。查看有关如何正确使用REAL(KIND=myRealKind)
的问题的答案:KIND
。
正如评论中提到的那样,一个更好的解决方案是将子例程和函数放入模块中,然后从主程序中使用该模块。这将使调用者知道这些过程的接口-在Fortran术语中为“显式”。编译器不仅可以正确处理函数的类型,还可以检查调用中的参数和被调用方中的参数(“虚拟参数”)之间的类型一致性,以确保一致性。
如果您使用尽可能多的调试选项,编译器将帮助您发现错误。使用gfortran,请尝试:-O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck = all -std = f2008 -pedantic -fbacktrace] >
Fortran 90 kind parameter您可能会发现,使用正整数只能通过直接乘法来计算非常小的整数的阶乘。一种解决方法是使用更大的整数类型,例如,
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
就像您可以现代化并使用selected_real_kind而不是Double Precision一样。
integer, parameter :: BigInt_K = selected_int_kind (18)