Fortran函数返回意外的类型和值 [英] Fortran functions returning unexpected types and values
问题描述
我正在一个需要在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语言功能页中提取了阶乘函数. /p>
- 编译器:带有Cygwin的gfortran 4.5.3
- IDE:Netbeans 7.0.1
- 平台:Windows 7
您的函数编写正确.问题出在主程序中,您没有显式声明integrate
和factorial
函数的类型,因此您具有隐式类型,在这种情况下,假定factorial
假定为REAL
,而假定integrate
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
注意IMPLICIT NONE
行.此声明语句将禁用任何隐式类型,并且如果未明确声明所有变量和函数,则编译器将引发错误.这是每个Fortran程序中非常重要的一行,如果有的话,您会自己解决问题,因为这将迫使您在程序中显式声明所有内容.
现在的输出是:
120
-19.0000000000000
符合预期.
作为旁注,DOUBLE PRECISION
类型声明不如使用REAL
并指定了KIND
参数的灵活,例如an REAL(KIND=myRealKind)
.查看有关如何正确使用KIND
的问题的答案: Fortran 90种类参数. /p>
I'm working on a project that needs to implement few numerical methods in Fortran. For this, I need to write some recursive functions. Here is my code.
!
! 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
For this program the output is:
NaN
1
If I change the order of the print statements (line 30 & 31), the output will be:
1
-19.000000
Output should be (for the original print statement order):
120
-19
I took the factorial function from the Wikipedia Fortran 95 language features page.
- Compiler : gfortran 4.5.3 with Cygwin
- IDE: Netbeans 7.0.1
- Platform: Windows 7
Your functions are written correctly. The problem is in the main program, where you do not explicitly declare the type of integrate
and factorial
functions, so you have implicit typing, in which case factorial
is assumed REAL
and integrate
is assumed INTEGER
. For some reason, your compiler did not warn you about type mismatch. Mine did:
$ 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))
You should change your main program to:
PROGRAM main
IMPLICIT NONE
DOUBLE PRECISION, EXTERNAL :: integrate
INTEGER, EXTERNAL :: factorial
PRINT *, factorial(5)
PRINT *, integrate(2)
END PROGRAM main
Notice the IMPLICIT NONE
line. This declaration statement will disable any implicit typing, and the compiler would throw an error if not all variables and functions are explicitly declared. This is a very important line in every Fortran program, and if you had it, you would've figured out your problem yourself, because it would force you to explicitly declare everything in your program.
The output now is:
120
-19.0000000000000
as expected.
As a side note, the DOUBLE PRECISION
type declaration is not as flexible as using REAL
with KIND
parameter specified instead, e.g. anREAL(KIND=myRealKind)
. See answers to this question about how to use KIND
properly: Fortran 90 kind parameter.
这篇关于Fortran函数返回意外的类型和值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!