Fortran - Procedimientos

UN procedurees un grupo de declaraciones que realizan una tarea bien definida y pueden invocarse desde su programa. La información (o datos) se pasa al programa de llamada, al procedimiento como argumentos.

Hay dos tipos de procedimientos:

  • Functions
  • Subroutines

Función

Una función es un procedimiento que devuelve una sola cantidad. Una función no debe modificar sus argumentos.

La cantidad devuelta se conoce como function value, y se indica con el nombre de la función.

Syntax

La sintaxis de una función es la siguiente:

function name(arg1, arg2, ....)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

El siguiente ejemplo demuestra una función denominada area_of_circle. Calcula el área de un círculo con radio r.

program calling_func

   real :: a
   a = area_of_circle(2.0) 
   
   Print *, "The area of a circle with radius 2.0 is"
   Print *, a
   
end program calling_func


! this function computes the area of a circle with radius r  
function area_of_circle (r)  

! function result     
implicit none      

   ! dummy arguments        
   real :: area_of_circle   
   
   ! local variables 
   real :: r     
   real :: pi
   
   pi = 4 * atan (1.0)     
   area_of_circle = pi * r**2  
   
end function area_of_circle

Cuando compila y ejecuta el programa anterior, produce el siguiente resultado:

The area of a circle with radius 2.0 is
   12.5663710

Tenga en cuenta que -

  • Debes especificar implicit none tanto en el programa principal como en el procedimiento.

  • El argumento r en la función llamada se llama dummy argument.

La opción de resultado

Si desea que el valor devuelto se almacene con un nombre diferente al nombre de la función, puede usar el result opción.

Puede especificar el nombre de la variable de retorno como -

function name(arg1, arg2, ....) result (return_var_name)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

Subrutina

Una subrutina no devuelve un valor, sin embargo, puede modificar sus argumentos.

Syntax

subroutine name(arg1, arg2, ....)    
   [declarations, including those for the arguments]    
   [executable statements]  
end subroutine [name]

Llamar a una subrutina

Necesita invocar una subrutina usando el call declaración.

El siguiente ejemplo demuestra la definición y uso de un intercambio de subrutinas, que cambia los valores de sus argumentos.

program calling_func
implicit none

   real :: a, b
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
end program calling_func


subroutine swap(x, y) 
implicit none

   real :: x, y, temp   
   
   temp = x  
   x = y 
   y = temp  
   
end subroutine swap

Cuando compila y ejecuta el programa anterior, produce el siguiente resultado:

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000

Especificar la intención de los argumentos

El atributo intent le permite especificar la intención con la que se utilizan los argumentos en el procedimiento. La siguiente tabla proporciona los valores del atributo de intención:

Valor Usado como Explicación
en intención (en) Usados ​​como valores de entrada, no cambiados en la función
afuera intención (fuera) Usados ​​como valor de salida, se sobrescriben
En fuera intención (inout) Los argumentos se utilizan y se sobrescriben

El siguiente ejemplo demuestra el concepto:

program calling_func
implicit none

   real :: x, y, z, disc
   
   x = 1.0
   y = 5.0
   z = 2.0
   
   call intent_example(x, y, z, disc)
   
   Print *, "The value of the discriminant is"
   Print *, disc
   
end program calling_func


subroutine intent_example (a, b, c, d)     
implicit none     

   ! dummy arguments      
   real, intent (in) :: a     
   real, intent (in) :: b      
   real, intent (in) :: c    
   real, intent (out) :: d   
   
   d = b * b - 4.0 * a * c 
   
end subroutine intent_example

Cuando compila y ejecuta el programa anterior, produce el siguiente resultado:

The value of the discriminant is
   17.0000000

Procedimientos recursivos

La recursividad ocurre cuando un lenguaje de programación le permite llamar a una función dentro de la misma función. Se llama llamada recursiva de la función.

Cuando un procedimiento se llama a sí mismo, directa o indirectamente, se denomina procedimiento recursivo. Debe declarar este tipo de procedimientos anteponiendo la palabrarecursive antes de su declaración.

Cuando una función se utiliza de forma recursiva, la result se debe utilizar la opción.

A continuación se muestra un ejemplo, que calcula el factorial para un número dado mediante un procedimiento recursivo:

program calling_func
implicit none

   integer :: i, f
   i = 15
   
   Print *, "The value of factorial 15 is"
   f = myfactorial(15)
   Print *, f
   
end program calling_func

! computes the factorial of n (n!)      
recursive function myfactorial (n) result (fac)  
! function result     
implicit none     

   ! dummy arguments     
   integer :: fac     
   integer, intent (in) :: n     
   
   select case (n)         
      case (0:1)         
         fac = 1         
      case default    
         fac = n * myfactorial (n-1)  
   end select 
   
end function myfactorial

Procedimientos internos

Cuando un procedimiento está contenido dentro de un programa, se denomina procedimiento interno del programa. La sintaxis para contener un procedimiento interno es la siguiente:

program program_name     
   implicit none         
   ! type declaration statements         
   ! executable statements    
   . . .     
   contains         
   ! internal procedures      
   . . .  
end program program_name

El siguiente ejemplo demuestra el concepto:

program mainprog  
implicit none 

   real :: a, b 
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
 
contains   
   subroutine swap(x, y)     
      real :: x, y, temp      
      temp = x 
      x = y  
      y = temp   
   end subroutine swap 
   
end program mainprog

Cuando compila y ejecuta el programa anterior, produce el siguiente resultado:

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000