function - varias - Funciones FORTRAN
varias graficas en r (3)
Como menciona uno de los comentarios, una mejor solución es poner sus subrutinas y funciones en un módulo, luego usar ese módulo desde su programa principal. Esto hará que la interfaz de esos procedimientos sea conocida por el que llama: "explícita" en la terminología de Fortran. El compilador no solo manejará correctamente el tipo de función, sino que también podrá verificar el acuerdo de tipo entre los argumentos en la llamada y los argumentos en el llamado ("argumentos ficticios") para mayor coherencia.
Si usa tantas opciones de depuración como sea posible, el compilador lo ayudará a encontrar errores. Con gfortran, pruebe: -O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsused -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
Probablemente descubrirá que solo puede calcular los factoriales de enteros muy pequeños mediante la multiplicación directa utilizando enteros regulares. Una solución es usar un tipo de entero más grande, por ejemplo,
integer, parameter :: BigInt_K = selected_int_kind (18)
Del mismo modo que podría modernizar y usar selected_real_kind en lugar de Double Precision.
Estoy trabajando en un proyecto que necesita implementar algunos métodos numéricos en FORTRAN. Para esto, necesito escribir algunas funciones recursivas. Aquí está mi código.
!
! 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
Para este programa, el resultado es:
NaN
1
Si cambio el orden de las instrucciones de impresión (líneas 30 y 31), la salida será:
1
-19.000000
La salida debe ser (para el orden de extracto de impresión original):
120
-19
Tomé la función factorial de la página de características de lenguaje de Wikipedia Fortran 95 . Soy nuevo en FORTRAN, no sé lo que está mal en mi código. Por favor, ayúdenme chicos.
- Compilador: gfortran 4.5.3 con Cygwin
- IDE: Netbeans 7.0.1
- Plataforma: Windows 7
Gracias de antemano.
Tus funciones están escritas correctamente. El problema está en el programa principal, donde no declaras explícitamente el tipo de funciones integrate
y factorial
, entonces tienes tipeo implícito, en cuyo caso factorial
se supone REAL
y se supone que INTEGER
. Por algún motivo, su compilador no le advirtió sobre el desajuste de tipos. El mío lo hizo
$ 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))
Debe cambiar su programa principal a:
PROGRAM main
IMPLICIT NONE
DOUBLE PRECISION, EXTERNAL :: integrate
INTEGER, EXTERNAL :: factorial
PRINT *, factorial(5)
PRINT *, integrate(2)
END PROGRAM main
Observe la línea IMPLICIT NONE
. Esta declaración de declaración desactivará cualquier tipeo implícito, y el compilador generará un error si no todas las variables y funciones se declaran explícitamente. Esta es una línea muy importante en cada programa de Fortran, y si lo tuviera, usted mismo habría resuelto su problema, porque lo obligaría a declarar explícitamente todo en su programa.
El resultado ahora es:
120
-19.0000000000000
como se esperaba.
Como nota al margen, la declaración de tipo DOUBLE PRECISION
no es tan flexible como usar REAL
con el parámetro KIND
especificado en su lugar, por ejemplo, un REAL(KIND=myRealKind)
. Vea las respuestas a esta pregunta sobre cómo usar KIND
correctamente: parámetro tipo Fortran 90 .
I would like to highlight some points while using RECURSIVE functions or non recursive function.
1. Asegúrese de que la función tenga una interfaz explícita con el programa de llamada. Esto se puede lograr poniendo la función en un módulo y la asociación USE. Esto se explica en la respuesta antes mencionada. 2. Puede usar INTERFACE para construir una interfaz explícita con el programa principal de llamadas, esto es útil cuando tiene muy pocos números de funciones que tengan una interfaz implícita, como en su caso. El ejemplo se da a continuación.
PROGRAM main
IMPLICIT NONE
INTERFACE
FUNCTION factorial(n)
INTEGER:: factorial
INTEGER, INTENT(IN):: n
END FUNCTION factorial
FUNCTION integrate(n)
DOUBLE PRECISION:: integrate
INTEGER, INTENT(IN):: n
END FUNCTION integrate
END INTERFACE
PRINT *, factorial(5)
PRINT *, integrate(2)
END PROGRAM main
tenga en cuenta que siempre es mejor definir un parámetro tipo y luego usar la cláusula KIND como! explicado por @milancurcic
Hay otra forma muy simple de resolver su problema: simplemente defina factorial e itegrate en el programa principal de la siguiente manera y ya está listo para comenzar
PROGRAM main
IMPLICIT NONE
DOUBLE PRECISION :: integrate
INTEGER:: factorial
PRINT *, factorial(5)
PRINT *, integrate(2)
END PROGRAM main