Wuolah Free Fortran 90 Libro
Wuolah Free Fortran 90 Libro
Wuolah Free Fortran 90 Libro
Rachel_
Informática
2. Bases de Fortran 9
2.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2. Notación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3. Normas de escritura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.4. Estructura general de un programa . . . . . . . . . . . . . . . . . . . . . . 11
2.5. Salidas de un programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3. Tipos de datos 15
3.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2. Tipos de datos intrı́nsecos . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2.1. Datos enteros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2.2. Datos reales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.2.3. Datos complejos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2.4. Datos lógicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2.5. Datos caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.3. Tipos de datos derivados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.4. Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.5. Parámetros dentro de un programa . . . . . . . . . . . . . . . . . . . . . . 32
3.6. La sentencia implicit none . . . . . . . . . . . . . . . . . . . . . . . . . . 32
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
3.7. Definición en la lı́nea de declaración . . . . . . . . . . . . . . . . . . . . . . 34
3.8. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4. Operaciones básicas 37
4.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.2. Expresiones aritméticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.3. Expresiones relacionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
4.4. Expresiones lógicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.5. Operaciones con caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.6. Operaciones con arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.7. Definición en la lı́nea de declaración . . . . . . . . . . . . . . . . . . . . . . 47
5. Control de flujo 49
5.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
5.2. Estructura condicional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.2.1. Estructura condicional simple . . . . . . . . . . . . . . . . . . . . . 51
6. Funciones intrı́nsecas 65
6.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
6.2. Funciones intrı́nsecas con datos numéricos . . . . . . . . . . . . . . . . . . 66
6.2.1. Funciones de conversión . . . . . . . . . . . . . . . . . . . . . . . . 67
6.2.2. Funciones de truncamiento y redondeo . . . . . . . . . . . . . . . . 68
6.2.3. Funciones matemáticas . . . . . . . . . . . . . . . . . . . . . . . . . 69
6.3. Funciones intrı́nsecas especı́ficas de caracteres . . . . . . . . . . . . . . . . 70
6.3.1. Funciones de conversión . . . . . . . . . . . . . . . . . . . . . . . . 70
6.3.2. Funciones de manipulación . . . . . . . . . . . . . . . . . . . . . . . 71
6.4. Funciones intrı́nsecas especı́ficas de arrays . . . . . . . . . . . . . . . . . . 74
6.4.1. Funciones de cálculo . . . . . . . . . . . . . . . . . . . . . . . . . . 74
6.4.2. Funciones de búsqueda . . . . . . . . . . . . . . . . . . . . . . . . . 76
6.4.3. Funciones de dimensiones . . . . . . . . . . . . . . . . . . . . . . . 79
ii
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
7.3. Datos de tipo derivado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
7.3.1. Componente de tipo array . . . . . . . . . . . . . . . . . . . . . . . 92
7.3.2. Componente de tipo estructura . . . . . . . . . . . . . . . . . . . . 94
iii
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
A. El conjunto de caracteres ASCII 155
B. Bibliografı́a 157
iv
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
2 1.1 Arquitectura de un ordenador
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• software o conjunto de programas disponibles.
• Memoria Solo de Lectura (ROM, Read Only Memory), de la que solo se puede leer.
La información reside en ella de forma permanente, aunque no exista suministro de
energı́a eléctrica. Esta memoria está reservada para instrucciones de arranque del
ordenador y otra información crı́tica.
Los dispositivos I/O son aquellos que aceptan datos para ser procesados (Entrada)
o presentan los resultados del procesamiento (Salida).
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Unidad de Memoria
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
1.2.1. Análisis del problema
El análisis consiste en estudiar el problema planteado para tener una idea clara de
los datos de partida, la forma en que éstos van a entrar en el programa, su tratamiento
para obtener el resultado final, los datos de salida y la forma en que éstos van a salir del
programa.
2.- Debe estar definido, si se sigue un mismo algoritmo dos veces se debe obtener idéntico
resultado.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.1 Proceso de diseño de un programa
Análisis
del problema
✲
❄
✲
❄ ❄
Verificación Ejecución
manual
del algoritmo del programa
Verificación
del programa
Documentación
o bien
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
6 1.2 Introducción a la programación
Problema
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Entrada Proceso Salida
de datos de datos
area =
base altura base × altura area
reglas de sintaxis propias de cada lenguaje. El algoritmo, una vez codificado, se denomina
programa.
Existen dos fases previas que debe realizar el ordenador antes de la ejecución del
programa
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
que contiene la traducción de nuestro programa a código máquina.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
10 2.1 Introducción
2.1. Introducción
El objetivo principal de la programación tal y como debe entenderse en un ámbito
cientı́fico e ingenieril, es la resolución numérica a través de un ordenador del problema
planteado. En este sentido Fortran constituye un lenguaje de programación estructurado
y de alto nivel orientado desde sus orı́genes, hace más de 40 años, a la resolución de
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
problemas cientı́ficos. De hecho su nombre no es más que la contracción de FORmula
TRANslation.
La primera versión de Fortran surgió a mediados de los sesenta como un intento
de unificar diferentes dialectos creados con el fin de conseguir un lenguaje intermedio
entre el lenguaje matemático y el lenguaje máquina (único conocido hasta esa fecha).
El resultado final, conocido como Fortran77, constituyó el paradigma de programación
durante muchos años, de ahı́ que muchas librerı́as estándar matemáticas como IMSL
(International Mathematics and Statistics Library) o NAG (Numerical Algorithmis Group)
usadas por cientı́ficos e ingenieros estuviesen escritas en esa versión. Durante los siguientes
2.2. Notación
A lo largo de todo el texto vamos a utilizar las siguientes convenciones, aunque en
ocasiones, por cuestiones de claridad, no seremos muy rigurosos en su cumplimiento.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Cuando parte de una sentencia sea opcional, irá metida entre corchetes
end if [ nombre ]
• Para especificar la existencia de espacios en blanco se utilizará el carácter
program nombre
Dec laración e inicialización de parámetros
Dec laración [ e inicialización ] de variables
sent encias de ejecución
end program nombre
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
.
.
z = 0.0 ! Inicializo la variable
.
.
z = 3.0 + x
• El nombre del programa no tiene porqué coincidir con el nombre del fichero que lo
• La frase a imprimir por pantalla es opcional pero, si se utiliza, debe ir entre comillas
(dobles o simples).
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
durante la implementación del código (división entre cero, fichero de lectura incorrecto,
memoria disponible insuficiente, . . . ). La sentencia stop constituye una manera de con-
trolar estas eventualidades por el propio programador. Aborta la ejecución del programa
y, por medio de una frase suficientemente clara, advierte del problema o error que se ha
producido.
Hay que tener en cuenta ciertas normas de uso extendido
• No hay que abusar del uso de la sentencia stop. Cuando se elabora el algoritmo hay
que intentar dar una solución a los posibles problemas que se pueden producir, sin
necesidad de abortar el programa.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
14
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Índice
3.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2. Tipos de datos intrı́nsecos . . . . . . . . . . . . . . . . . . . . . 18
3.2.1. Datos enteros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2.2. Datos reales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.2.3. Datos complejos . . . . . . . . . . . . . . . . . . . . . . . . . . 21
15
3.1. Introducción
Los programas, con independencia del lenguaje en que se escriban, están diseñados
para manipular información o datos. En Fortran se pueden definir y manipular varios tipos
de datos. Por ejemplo, se puede asignar el valor 10 a una variable llamada i definida como
entera. En este caso tanto 10 como i son de tipo entero. 10 es un valor constante mientras
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
que i es una variable que puede modificar su valor a lo largo del programa. Además de
las constantes y variables existe la posibilidad de definir un parámetro, un dato cuyo valor
no cambia durante la ejecución del programa.
Un tipo de dato consiste en
• Un identificador de tipo
• Un conjunto válido de valores
• Una forma de denotar sus valores
• Un conjunto de operaciones válidas
Por ejemplo, para un dato de tipo entero, el identificador de tipo es integer, el
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
En adición a los datos simples, ya sean de tipo intrı́nseco o derivado, es posible
generar una colección de datos del mismo tipo e igual kind denominada array, usada
normalmente para materializar vectores, matrices y tablas de más dimensiones.
Cuando nos planteamos resolver un problema cientı́fico con un ordenador, gene-
ralmente nos centramos en el conjunto de operaciones que se tienen que realizar y en
qué orden. Sin embargo, es igual de importante tener muy claro, antes de escribir el pro-
grama, el tipo de datos que vamos a manejar. En muchas ocasiones, un programa bien
escrito y estructurado produce resultados erróneos debido a una elección incorrecta del
tipo de dato utilizado. Ası́ pues,
• Para las operaciones numéricas más comunes es aconsejable utilizar datos de
1 program main
2 integer :: n
3 n = 20
4 write (* ,*) 5* n
5 n = n + 1
6 end program main
En la figura 3.1 se muestra un ejemplo del uso de una variable entera llamada n. En la
lı́nea 2 se realiza la declaración de la variable. En ese momento, la variable está indefinida,
es decir no tiene un valor asignado. En la lı́nea 3 se asigna a n el valor 20 y pasa a estar
definida. En la lı́nea 4, después de asignarle un valor, ya puede ser referenciada, es decir
podemos utilizar la variable, y por tanto el dato que contiene, para realizar operaciones.
En el momento de la declaración (lı́nea 2), el procesador habilita una zona de me-
moria con la etiqueta n a la que puede acceder a lo largo de la ejecución del programa. En
este paso, la variable está indefinida ya que, aunque la zona de memoria está reservada,
en ella no hay ningún dato almacenado. En la lı́nea 3 se produce una asignación y el dato
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
18 3.2 Tipos de datos intrı́nsecos
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Todos los datos utilizados en un programa deben:
El rango de valores que puede tomar un dato de tipo entero depende, por una
parte, del procesador (32-bit ó 64-bit) y, por otra, del parámetro kind especificado en la
declaración.
program main
integer :: n
n = 20
n = -2
n = 0
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
n = 9999
end program main
program main
integer ( kind =1) :: i
integer (1) :: j
integer ( kind =4) :: k
integer (4) :: l
integer ( kind =8) :: m
integer (8) :: n
end program main
Las constantes literales asociadas a un dato real pertenecen al conjunto de los núme-
ros reales. Se pueden representar en modo decimal o en modo exponencial. Las constantes
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
reales negativas deben estar precedidas por el signo menos, sin embargo, en las no nega-
tivas el signo es opcional.
Si un dato real se representa en modo decimal es necesario utilizar el punto decimal
(la coma decimal no está permitida). La representación en modo exponencial consiste en
un número entero o real seguido por la letra e y el número entero como exponente. En
la figura 3.4 se muestran distintas formas de representar la constante real 20.508, todas
ellas equivalentes entre sı́.
El rango de valores que puede tomar un dato de tipo real depende, por una parte, del
procesador (32-bit ó 64-bit) y, por otra, del parámetro kind especificado en la declaración.
Los identificadores de especie más comunes son:
◦ kind = 4 (valor por defecto)
El dato ocupa 4 bytes de memoria y se pueden representar datos reales comprendidos
entre 1.18×10−38 y 3.40×1038 . La precisión en coma flotante es 1.19×10−7 . Cuando
un dato se declara con kind=4 se dice que es un dato en simple precisión.
◦ kind = 8
El dato ocupa 8 bytes de memoria y se pueden representar datos reales comprendidos
entre 2.23 × 10−308 y 1.79 × 10308 . La precisión en coma flotante es 2.22 × 10−16 .
Cuando un dato se declara con kind=8 se dice que es un dato en doble precisión.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
◦ kind = 16
El dato ocupa 16 bytes de memoria. Generalmente los ordenadores personales no
tienen capacidad para trabajar con este kind, pero sı́ las estaciones de trabajo y los
ordenadores de gran potencia de cálculo.
program main
real ( kind =4) :: x
real (4) :: y
real ( kind =8) :: z
Tanto el rango valores como la precisión de los datos reales en simple y doble pre-
cisión presentados anteriormente son meramente orientativos.
Los datos de tipo complex admiten los mismos identificadores de especie ya definidos
para datos de tipo real, y se aplican tanto a la parte real como a la imaginaria. Por tanto,
si el kind es 8, el dato complejo ocupará 16 bytes de memoria (8 la parte real + 8 la parte
imaginaria). Si no se especifica el kind, por defecto se asume que vale 4.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
22 3.2 Tipos de datos intrı́nsecos
program main
complex :: z
z = (20.508 , 3.7)
z = (205.08 e -1 , 3.7)
z = (2.0508 e +1 , 37 e -1)
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
z = (20.508 , 0.37 e +1)
end program main
program main
complex ( kind =4) :: x
complex (4) :: y
complex ( kind =8) :: z
Las constantes literales asociadas a un dato lógico son, en su forma más básica,
.true. (verdadero) o .false. (falso).
program main
logical :: x
x = . true .
x = . false .
end program main
Al igual que en el caso de los datos de tipo numérico, los datos de tipo lógico admiten
un identificador de especie. El valor por defecto del identificador o default kind depende
del procesador.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
dobles. Por ejemplo
’ Esto es un mensaje ’
" Esto tambien "
’D . E . Knuth & M . Metcalf ’
Las comillas dobles o simples son solo delimitadores, no forman parte del valor del
dato. El valor de la constante literal ’hola’ es hola. Sı́ hay que tener en cuenta que
los espacios en blanco son caracteres, y que, como carácter, las mayúsculas son distintas
de las minúsculas. Ası́, las constantes ’un saludo’ y ’ un saludo’ son distintas y las
Una forma alternativa de introducir una comilla simple en una constante literal es
mediante dos comillas simples seguidas, sin ningún carácter entre ellas. El valor de la
constante ’don’’t work’ es don’t work.
La longitud de una constante literal de tipo carácter coincide exactamente con el
número de caracteres de impresión contenidos entre los delimitadores.
program main
character :: c_1
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
character ( len =4) :: c_2
character ( len =10) :: c_3
character ( len =13) :: c_4
character ( len =13) :: c_5
c_1 = ’P ’
c_2 = " Hola "
c_3 = ’ Adios ’
c_4 = " Hola & Adios "
c_5 = ’ Hola & Adios ’
end program main
Un dato de tipo character, por ejemplo ch, declarado con una longitud especı́fica,
por ejemplo 10, se puede entender como una cadena de 10 caracteres de longitud 1.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Podemos acceder a la subcadena formada por los caracteres que van desde el carácter
i-ésimo hasta el j-ésimo utilizando la expresión ch(i:j), siendo i y j dos datos simples
de tipo integer (Fig. 3.11).
program main
character ( len =10) :: ch
integer :: i
integer :: j
ch = ’ carbonilla ’
type persona
character ( len =10) :: nombre
character ( len =20) :: apellido
integer :: edad
real :: altura
end type persona
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
26 3.3 Tipos de datos derivados
Mientras que para declarar un dato, llamado yo, del tipo derivado persona, la
sentencia serı́a
type ( persona ) :: yo
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
declarado una estructura llamada yo que es de tipo persona.
Para referenciar una componente individual de una estructura es necesario utilizar
un selector de componentes, el carácter tanto por ciento ( %), en la secuencia:
estructura %componente
Hay que tener en mente que cuando trabajamos con una componente, estamos traba-
jando con un dato de tipo intrı́nseco. Por ejemplo, persona %edad es una variable de tipo
entero, con las mismas propiedades y caracterı́sticas que cualquier otra variable integer
del programa. Sus constantes literales pertenecen al conjunto de los números enteros,
puede estar declarada con un kind especı́fico, etc.
Una estructura se dice que está definida si, y solo si, lo están cada una de sus
componentes. Para definir una estructura podemos utilizar dos estrategias (Fig. 3.12)
a) Definir las componentes una a una. Para ello, se accede a cada una de las componen-
tes de forma independiente y se le asigna una constante literal apropiada a su tipo
intrı́nseco y en la forma habitual para ese tipo intrı́nseco. Como estamos trabajando
de forma independiente, el orden en el que se definen las componentes no afecta al
resultado final.
b) Definir todas las componentes a la vez. Para ello, se utiliza la fórmula: nombre del
tipo derivado seguido, entre paréntesis, por las constantes literales asignadas a las
componentes, en el mismo orden en el que han sido declaradas.
program main
type persona
character ( len =10) :: nombre
character ( len =20) :: apellido
integer :: edad
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
real :: altura
end type persona
3.4. Arrays
Un array es una colección de datos, denominados elementos, todos ellos del mismo
tipo y kind, situados en posiciones contiguas de memoria. Los arrays se clasifican en
unidimensionales (vectores), bidimensionales (matrices) y multidimensionales (tablas).
Existen varias formas de declarar un array pero, por el momento, utilizaremos el
modo más sencillo de declarar arrays de forma explı́cita, consistente en especificar el tipo,
el kind, el nombre y la extensión de cada dimensión del array, utilizando (Fig. 3.14) o no
(Fig. 3.13) el atributo dimension.
program main
integer :: U (5) ! Vector
real :: V (10) ! Vector
real :: A (2 ,3) ! Matriz de 2 x3
real :: Z (3 ,2) ! Matriz de 3 x2
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
real :: T (0:2 , -1:0) ! Matriz de 3 x2
character ( len =2) :: Mch (3 ,2) ! Matriz de 3 x2
integer :: Tabla (2 ,3 ,4) ! Tabla de 2 x3x4
end program main
program main
integer , dimension (5) :: U ! Vector
real , dimension (10) :: V ! Vector
• Lı́mites del array. Son los lı́mites inferior y superior de los ı́ndices de las dimensiones.
Si no se especifica el lı́mite inferior, su valor por defecto es 1. U tiene lı́mite superior
5, V tiene lı́mite superior 10, A tiene lı́mites superiores 2 y 3, Z y Mch tiene lı́mites
superiores 3 y 2, T tiene lı́mites superiores 2 y 0 y Tabla tiene lı́mites superiores
2, 3 y 4. Todos los arrays tienen lı́mite inferior 1 en cada una de sus dimensiones
excepto T que tiene lı́mites inferiores 0 y -1.
• Extensión del array. Es el número de elementos (puede ser cero) en cada dimensión.
U tiene extensión 5, V tiene extensión 10, A tiene extensiones 2 y 3, Z, T y Mch tienen
extensiones 3 y 2, y Tabla tiene extensiones 2, 3 y 4.
• Tamaño del array. Indica el número total de elementos. U tiene tamaño 5, V tiene
tamaño 10, A, Z, T y Mch tienen tamaño 6, y Tabla tiene tamaño 24.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Forma del array. Viene dada por el rango y la extensión. U tiene forma 5, V tiene
forma 10, A tiene forma 2 × 3, Z, T y Mch tiene forma 3 × 2, y Tabla tiene forma
2 × 3 × 4.
• Conforme. Dos arrays se dice que son conformes, si tienen la misma forma.
Un array se identifica por su nombre, que debe seguir las mismas reglas que los
identificadores de los datos simples. Por ejemplo: A, Tabla, . . . Un elemento de un array
se referencia por el nombre del mismo y su posición. Esta posición viene dada por uno o
varios subı́ndices dados entre paréntesis. Por ejemplo, U(3) es el tercer elemento del vector
U; A(2,3) es el elemento de la fila 2 y columna 3 de la matriz A y T(0,-1) es el elemento
program main
integer :: U (5) ! Vector
real :: V (10) ! Vector
real :: A (2 ,3) ! Matriz de 2 x3
real :: Z (3 ,2) ! Matriz de 3 x2
real :: T (0:2 , -1:0) ! Matriz de 3 x2
character ( len =2) :: Mch (3 ,2) ! Matriz de 3 x2
integer :: Tabla (2 ,3 ,4) ! Tabla de 2 x3x4
V = 2.0
Tabla = 8
U = (/2 , -3 , 0 , 5 , 8/)
A = reshape ((/1.1 , 1.2 , 3.8 , 5.5 , 4.3 , 7.0/) , (/2 ,3/))
Z = reshape ((/1.1 , 1.2 , 3.8 , 5.5 , 4.3 , 7.0/) , (/3 ,2/))
T = reshape ((/1.1 , 1.2 , 3.8 , 5.5 , 4.3 , 7.0/) , (/3 ,2/))
Mch = reshape ((/ ’ ab ’ , ’ cd ’ , ’ ef ’ , ’ uv ’ , ’ wx ’ , ’ yz ’/) , (/3 ,2/))
end program main
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
30 3.4 Arrays
a) Para asignar el mismo valor a todos los elementos del array, se utiliza el modo
habitual de asignación:
dado que una constante literal se considera conforme a cualquier array. Por ejemplo,
las sentencias
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
V = 2.0
Tabla = 8
• En lenguaje matemático:
V1 = 2 V2 = 2 . . . V10 = 2
T abla111 = 8 T abla211 = 8 . . . T abla234 = 8
b) Para asignar distintas constantes literales, tantas como indique el tamaño del array,
se introduce la lista de las constantes entre los sı́mbolos de apertura y cierre (/ y
/), respectivamente. Además,
U = (/2 , -3 , 0 , 5 , 8/)
teniendo siempre en cuenta que, en el orden natural de los elementos del array,
los ı́ndices varı́an más rápidamente de izquierda a derecha (Fig. 3.16)
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
. . .
b(1,1) b(1,2) b(1,3) b(1,4)
• En lenguaje de programación:
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Mch(1,1)=’ab’ Mch(1,2)=’uv’ Mch(2,1)=’cd’
Mch(2,2)=’wx’ Mch(3,1)=’ef’ Mch(3,2)=’yz’
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 3.17 Asignación de un parámetro
program main
real , parameter :: g = 9.80665
integer , parameter :: l = 5
integer , parameter :: m = 2
integer , parameter :: n = 3
integer , parameter :: s = 4
integer , parameter :: n1 = 0
integer , parameter :: m1 = -1
integer , dimension ( l ) :: U ! Vector
real , dimension (n , m ) :: Z ! Matriz de 3 x2
algún dato y además, olvidar esta regla, con lo que es posible que datos que queremos
que sean integer el programa los trate como real y viceversa.
Para evitar este riesgo, es aconsejable utilizar la sentencia implicit none. Esta
sentencia, situada antes del cuerpo de las declaraciones, invalida todas las declaraciones
implı́citas y obliga a declarar todos los objetos que vayan a ser utilizados a lo largo del
programa.
program main
implicit none
integer :: m
integer :: n
real :: z
.
.
end program main
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
34 3.7 Definición en la lı́nea de declaración
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
inicialización con constantes literales.
integer , parameter :: n = 5
integer , parameter :: m = 2
integer , dimension (3) :: U = (/1 , 5 , 8/)
real , dimension (n , m ) :: A = 33.0
character ( len =4) :: Mch = ’ hola ’
3.8. Resumen
• Además de los 5 tipos intrı́nsecos, Fortran posee dos herramientas muy poderosas
para ampliar los tipos de datos:
◦ Los datos derivados, útiles para crear objetos abstractos que agrupan datos de
distintos tipos.
◦ Los arrays, asociados al concepto matemático de vector o matriz.
• Declarar un dato significa asignarle un tipo. Cada tipo tiene su propio rango de
valores válidos. Si el tipo del dato no coincide con el tipo de la constante literal que
se pretende asignar, siempre prevalece el tipo con el que se ha declarado el dato.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
type persona
character(len=20) :: nombre
tipo
integer :: edad componente
derivado
real :: altura
end type persona
5
3.8
constante
(2.0, 3.5) literal
’hola’
.true.
A(1,3)
U(2) elemento
ellos(10)
37
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
38 4.1 Introducción
4.1. Introducción
En el lenguaje natural existen letras que forman palabras que, combinadas siguiendo
las reglas gramaticales establecidas, generan las frases lógicas con las que nos comunica-
mos. Del mismo modo en Fontran existen los datos que, como las letras forman expresiones
que se combinan siguiendo las reglas propias de este lenguaje de programación, para for-
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
mar sentencias.
A diferencia de lo que ocurre en el lenguaje natural donde la comunicación es posible
aun cuando la frase sea gramaticalmente incorrecta, en programación las reglas “grama-
ticales” se deben cumplir de forma estricta, pues la comunicación se establece con una
máquina, es decir un objeto incapaz de interpretar una ambigüedad.
Una expresión en Fortran está formada por operandos y operadores, combinados si-
guiendo las reglas sintácticas propias del lenguaje. Una expresión simple se puede construir
utilizando un operador binario en la forma
x *5
operador operando
por ejemplo
-x
Los operandos pueden ser constantes literales, datos o incluso otras expresiones,
dando lugar a expresiones más complejas del tipo
Evidentemente, cada operando debe estar definido antes de ser utilizado en una ex-
presión y la propia expresión debe ser conceptualmente correcta. Por ejemplo, matemáti-
camente es incorrecto establecer una relación de orden entre dos números complejos.
La regla seguida en Fortran para la evaluación de las diferentes partes de una expre-
sión compleja es que son evaluadas sucesivamente de izquierda a derecha, para operadores
de la misma precedencia, salvo en el caso de la potenciación. Si, al margen de esta regla,
interesa evaluar primero ciertas subexpresiones, éstas deben ir encerradas entre paréntesis.
Solo es posible que en una expresión aparezcan dos operadores seguidos si el segundo
es unario. Es decir en una expresión del tipo
el segundo operador nunca puede ser un operador binario. En cualquier caso, sea obliga-
torio o no, por cuestiones de claridad es recomendable utilizar paréntesis para separar las
distintas operaciones de una misma sentencia.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
En las siguientes tres secciones de este capı́tulo expondremos las propiedades de
las expresiones intrı́nsecas de Fortran que involucran como operandos datos simples (ex-
presiones aritméticas, relacionales y lógicas). Las dos últimas secciones se ocupan de dos
casos particulares: los datos de tipo character y los arrays.
a*b/c
es equivalente a
( a * b )/ c
mientras que
a ** b ** c
se evalúa como
a **( b ** c )
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
-a + b + c
x **( - b )
Cuando se opera con datos numéricos de distinto tipo y kind, es necesario tener en
cuenta que el resultado es del tipo con mayor rango de los involucrados en la operación.
De hecho, antes de evaluar la expresión se convierten los operandos al tipo más fuerte
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Tabla 4.3 Tipo de resultado de a**b
Tipo de Tipo de Valor usado Valor usado Tipo de
a b de a de b resultado
integer integer a b integer
integer real real(a,kind(b)) b real
integer complex cmplx(a,0,kind(b)) b complex
real integer a b real
real real a b real
real complex cmplx(a,0,kind(b)) b complex
complex integer a b complex
En la tabla 4.4 se muestran algunos ejemplos prácticos, muy útiles para comprender
mejor las reglas de conversión.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
42 4.3 Expresiones relacionales
tipo. Los operadores relacionales que Fortran dispone de modo intrı́nseco vienen dados
en la tabla 4.5.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<= Menor o igual que
== Igual que
/= Distinto que
> Mayor que
>= Mayor o igual que
1 i <= 0
2 a > b
3 ( a + b ) > (i - j )
4 a+b > i-j
5 ch == ’Z ’
Las expresiones de las lı́neas 3 y 4 son de tipo mixto en el sentido de que en ellas
aparecen datos de distinto tipo. Además, intervienen relaciones aritméticas. Como regla
general, siempre que en una expresión relacional intervengan datos numéricos de distinto
tipo o kind, antes de evaluar la expresión relacional, los datos numéricos se convierten
al tipo y kind de mayor rango de los involucrados. Ası́, en las sentencias de las lı́neas
3 y 4, después de realizar la operación (i-j) el resultado se convierte a tipo real y se
compara con el resultado de la operación (a+b). Respecto al orden en el que se evalúan las
expresiones, primero se realizan las operaciones aritméticas y luego las relacionales, por
lo que las sentencias de las lı́neas 3 y 4 son equivalentes. Para evitar confusiones conviene
utilizar siempre los paréntesis.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
control que gobiernan el flujo de un programa. El resultado de evaluar una expresión
lógica es de tipo logical y, por tanto, solo puede tomar uno de los valores .true. o
.false.. Los operadores lógicos que Fortran dispone de modo intrı́nseco vienen dados en
la tabla 4.6 en orden decreciente de precedencia.
La figura 4.3 recoge algunos ejemplos de expresiones que involucran los 3 tipos de
operadores vistos hasta ahora.
Cuando en una expresión lógica interviene alguno de los operadores .and. u .or.
no existe una regla definida sobre el orden en el que se evalúan los operandos. Incluso,
dependiendo del procesador, puede ocurrir que alguno de los operandos no llegue a ser
evaluado. Por ejemplo, dadas dos variables de tipo integer con valores i=6 y j=4, en la
expresión
( j < 5) . or . ( i < 5)
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
a = .false. y b = .false.
a.eqv.b
a = .true. y b = .false.
.false. Si o
a = .false. y b = .true.
a = .true. y b = .false.
.true. Si o
a = .false. y b = .true.
tendrán que evaluar también la de la izquierda. Por último, existen procesadores que, al
margen del valor de los operandos, evalúan todas las subexpresiones involucradas.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 4.3 Ejemplo con operadores aritméticos, relacionales y lógicos
program main
type persona
character ( len =20) :: nombre
integer :: edad
end type
integer :: i
integer :: j
integer :: k
integer :: U (4)
logical :: F1
el valor del resultado con tantos caracteres blanco a la derecha como sea necesario para
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
46 4.5 Operaciones con caracteres
completar la longitud long dato. Si por el contrario es menor, se trunca el valor del
resultado a los primeros long dato caracteres (Fig. 4.4).
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
character(len=12) :: Ag2
character(len=7) :: Ag3
character(len=6) :: nombre
character(len=3) :: numero
nombre = ’Agente’
numero = ’007’
Ag1 = nombre//numero ! Ag1 = Agente007
Ag2 = nombre//numero ! Ag2 = Agente007
Ag3 = nombre//numero ! Ag3 = Agente0
Mención especial merecen las expresiones relacionales en las que los operandos son
de tipo character. En todos los procesadores los caracteres poseen una propiedad de-
nominada secuencia de comparación, que ordena la colección de caracteres asignándoles
un número de orden. Aunque cada procesador puede tener su propia secuencia, la ma-
yorı́a utiliza la secuencia definida por el estándar ASCII (del inglés, American Standard
Code for Information Interchange). Sin embargo, Fortran está diseñado para adaptarse
a otras secuencias como, por ejemplo la secuencia EBCDIC (del inglés, Extended Binary
Coded Decimal Interchange Code) desarrollada por IBM. Esto implica que, en general,
por cuestiones de portabilidad, no es conveniente que un programa fundamente parte de
su algoritmo en la relación entre datos de tipo character. En el apéndice A se muestra
una tabla completa del conjunto de caracteres ASCII ası́ como su número de orden.
En cualquier caso, la comparación entre dos operandos de tipo character se realiza
carácter a carácter de izquierda a derecha siguiendo el orden alfabético para las letras y
el numérico para los dı́gitos. Si los operandos no tienen la misma longitud, el de menor
longitud se rellena con espacios en blanco a la derecha hasta completar la longitud máxima
antes de realizar la comparación (Fig 4.5).
program main
character ( len =3) :: ch
ch = ’abc ’
write (* ,*) ch == ’Abc ’ ! falso
write (* ,*) ch == ’ abc ’ ! falso
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
write (* ,*) ch == ’ abc ’ ! verdadero
write (* ,*) ch > ’abg ’ ! falso
write (* ,*) ch > ’aba ’ ! verdadero
write (* ,*) ch < ’ ab ’ ! falso
write (* ,*) ch < ’ ab ’ ! falso
write (* ,*) ch > ’ abc ’ ! falso
write (* ,*) ch >= ’ abc ’ ! verdadero
end program main
integer , parameter :: n = 3
integer , parameter :: m = n -1
integer , dimension (3) :: U = n * m
real , dimension (n , m ) :: A = reshape ((/1 , 0 , 2 , 8 , 3 , 1/) , (/ n , m /))
character ( len =8) :: Mch = ’ hola ’// ’ pepe ’
logical :: flag = ( m < n )
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 4.6 Operaciones con arrays
program main
integer :: U (3)
integer :: V (3)
logical :: Luv (3)
integer :: a (2 ,3)
49
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
50 5.1 Introducción
5.1. Introducción
Para aumentar la eficiencia de la programación es necesario que los programas tengan
una estructura fácil de interpretar, manejar y modificar. Los criterios de programación que
cumplen estos objetivos son la programación estructurada y la programación modular. No
son criterios contrapuestos, sino complementarios. El modular tiende a dividir el programa
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
en programas más pequeños, llamados subprogramas, mientras que el estructurado se
encarga de desarrollar estructuradamente cada uno de los subprogramas.
En este capı́tulo nos centraremos en la programación estructurada, dejando la mo-
dular para capı́tulos posteriores.
En un programa, las sentencias se ejecutan de forma secuencial o lineal. A menudo,
conviene no utilizar esta secuencia sino modificarla a medida que se van haciendo los
cálculos. La base de la programación estructurada es que todo programa puede ser escrito
utilizando solo tres tipos de estructuras de control de ejecución,
• secuencial
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Una estructura condicional es aquella que ejecuta un conjunto u otro de senten-
cias, dependiendo de si se cumple o no una determinada condición. Existen tres tipos de
estructuras condicionales: simples, dobles y múltiples.
Por ejemplo, queremos intercambiar los valores de x e y solo en el caso en que x sea
menor que y. El algoritmo serı́a:
if ( x < y ) then
temp = x
x = y
y = temp
end if
Como simplificación, en el caso de que solo haya una sentencia de ejecución dentro
de la estructura, el lenguaje permite la siguiente variación
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 5.2 Ejemplo con estructura condicional simple. Cálculo del valor absoluto
program ValorAbsoluto
real :: x
write (* ,*) ’ Introducir el valor de x ’
read (* ,*) x
if ( x < 0.0) x = -x
write (* ,*) ’ El valor absoluto de x es ’, x
end program ValorAbsoluto
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 5.4 Ejemplo con estructura condicional doble. Resolver ax + b = 0
program raiz
real :: a
real :: b
real :: x
write (* ,*) ’ Introducir los valores de a y b ’
read (* ,*) a , b
if ( a /= 0.0) then
x = -b / a
write (* ,*) ’ La solucion de la ecuacion es x = ’, x
else
5.2.3.1. Construcción if
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
54 5.2 Estructura condicional
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
❅
q
sent11 1
q
❅ sentencia21 1
q
.true. expr. ❅.false.
q q
lógica2
q
❅
❅
sent11 n ❅ sentencia21 n
❄ ❄
else
q q
sent21 1 sent22 1
q
sentencia22 1
q q
q q q
q
sent21 n sent22 n sentencia22 n
❄ ❄ ❄
❄ end if
sentencias 1
else if (expr. lógica2) then
sentencias 2
else if (expr. lógica3) then
sentencias 3
..
.
[ else
sentencias n]
end if [ nombre ]
program raices
real :: a
real :: b
real :: c
real :: disc
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
real :: x1
real :: x2
complex :: z1
complex :: z2
disc = b * b - 4.0* a * c
if ( disc < 0.0) then
❄
❅
expr.❅
❅
#1 ❄ #2 ❄ ❅ ❄
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
q q q
sent1 1 sent2 1 sentN 1
q q q
q
sentencia1 1
q
sentencia2 1
q
q
q
sentencia2 n
q
q
[case default
q
sentenciaN 1
q
q
sentenciaN n]
end select [nombre]
donde
• expr. case es una expresión escalar de tipo integer, character o logical. Por
ejemplo, el nombre de un dato simple de uno de estos tipos, i, o una expresión
aritmética, i*j+2
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• rango de valores puede tomar un único valor, varios valores o un rango de valores,
según se escriba de la forma
program ejemplo_case
integer :: num
write (* ,*) ’ Introducir un numero entero ’
read (* ,*) num
select case ( num )
case (: -1)
write (* ,*) ’ numero <= -1 ’
case (1 , 3 , 5 , 7 , 9)
write (* ,*) ’ 1 <= numero <= 9 e impar ’
case (2 , 4 , 6 , 8)
write (* ,*) ’ 2 <= numero <= 8 y par ’
case (0 , 10:200)
write (* ,*) ’ 10 <= numero <= 200 o 0 ’
case (205:)
write (* ,*) ’ numero >= 205 ’
case default
write (* ,*) ’ 201 <= numero <= 204 ’
end select
end program ejemplo_case
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
58 5.3 Estructura iterativa
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
por un contador o por una expresión lógica.
donde,
• vi,vf,p son constantes o variables de tipo integer, tales que vi es el valor inicial
del contador, vf es el valor final del contador y p es el incremento.
• Cuando se produce una salida normal del rango, el contador vale i=vi+p*(1+(vf-vi)/p)
• Dentro del rango del bucle se puede redefinir el contador, y este cambio queda
reflejado en el siguiente paso, por lo que en esta asignatura no estará permitido
hacerlo.
• Dentro del rango se pueden cambiar los valores de las variables vi, vf o p, y aunque
estos cambios no afectan al proceso de variación del contador establecido en el inicio
del bucle, en esta asignatura no estará permitido hacerlo.
• El número de iteraciones realizadas tras una salida normal del bucle do viene dado
por la expresión n o
máx (vf − vi + p)/p, 0
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Ejemplos tı́picos del uso de estructuras iterativas lo constituyen el cálculo del suma-
torio y el productorio. En las figuras 5.11 y 5.12 se utiliza la construcción do con contador
para calcular la suma de los n primeros números naturales y el factorial de un número
entero no negativo, respectivamente. Nótese que estamos haciendo uso de una estructura
iterativa dentro de una condicional.
program Sumatorio
program Factorial
integer :: n
integer :: Fact
integer :: i
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
write (* ,*) ’ Introducir un numero entero no negativo ’
read (* ,*) n
1. Para definir un array cuyos elementos siguen una regla iterativa sencilla.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
ı́ndice del mismo, y para imprimir una matriz A tal y como lo hacemos matemáticamente,
es decir, por filas.
program main
integer , parameter :: n = 5
integer , parameter :: m = n +1
real :: U ( n )
real :: A (n , m )
integer :: i
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
62 5.3 Estructura iterativa
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
if (expr. lógica) exit
..
.
sentencia r
end do [ nombre ]
! lectura de la cota
do
write (* ,*) ’ Introducir un numero entero positivo ’
read (* ,*) cota
if ( cota > 0) exit
end do
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 5.16 Sentencia cycle
[ nombre: ] do [ i=vi,vf [ , p ] ]
sentencia 1
..
.
BUCLE if (expr. lógica) cycle RANGO
..
.
sentencia r
65
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
66 6.1 Introducción
6.1. Introducción
Dada la orientación de Fortran hacia la resolución de problemas cientı́ficos, es lógico
que las funciones matemáticas más básicas formen parte del propio lenguaje y no tengan
que ser programadas por el usuario. Además estas funciones han sido programadas del
modo más eficiente, aprovechando al máximo los recursos del compilador, por lo que
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
resulta muy difı́cil competir con ellas.
En este capı́tulo estudiaremos las funciones intrı́nsecas siguiendo una clasificación
basada en el tipo de sus argumentos:
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
función devuelto argumento función
cmplx(x) = x + i0.0
cmplx(x, y) = x + iy
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Nombre Valor Tipo Tipo
función devuelto argumento función
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
6.2.3. Funciones matemáticas
En esta sección se estudian (Tabla 6.3) las funciones tı́picas para la realización de
las operaciones matemáticas.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
70 6.3 Funciones intrı́nsecas especı́ficas de caracteres
Para todas aquellas funciones matemáticas que por definición son multivaluadas, el
valor retornado es el valor principal. Además de las funciones listadas, suficientemente
auto-explicativas, a continuación se detallan otras funciones de uso común.
abs(x)
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
precisión, siendo (
x Si x >= 0
abs(x) =
−x Si x < 0
• Si x es de tipo complex entonces
p
abs(x) = Re2 (x) + Im2 (x)
sign(x,y)
Transfiere el signo del argumento y al argumento x. Los argumentos deben ser ambos
mod(x,y)
Calcula el resto de la división x/y. Los argumentos deben ser ambos de tipo integer
o real. (
x − int(x/y) × y Si y 6= 0
mod(x, y) =
depende del compilador Si y = 0
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
iachar(ch) Número de orden, dentro de la se- character integer
cuencia de comparación ASCII, del
carácter ch
char(i) Carácter situado en la posición i de integer character
la secuencia de comparación del pro-
cesador
ichar(ch) Número de orden, dentro de la se- character integer
cuencia de comparación del procesa-
dor, del carácter ch
len(string)
Devuelve la longitud de string
len(’ Fortran & magic ’) = 20
len trim(string)
Devuelve la longitud de string sin contar los espacios en blanco de la derecha.
len_trim(’ Fortran & magic ’) = 17
trim(string)
Devuelve el mismo string pero quitando los espacios en blanco de la derecha.
trim(’ Fortran & magic ’) = ’ Fortran & magic’
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
write(*,*) len(trim(ch)) ! resultado = 17
end program main
adjustl(string)
Ajusta string a la izquierda, manteniendo su longitud
adjustl(’ Fortran & magic ’) = ’Fortran & magic ’
adjustr(string)
Ajusta string a la derecha, manteniendo su longitud
index(’aderezado’, ’a’) = 1
index(’aderezado’, ’a’, back=.true.) = 7
index(’aderezado’, ’A’) = 0
index(’aderezado’, ’A’, back=.true.) = 0
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
index(’aderezado’, ’ad’) = 1
index(’aderezado’, ’ad’, back=.true.) = 7
index(’aderezado’, ’ae’) = 0
index(’aderezado’, ’ae’, back=.true.) = 0
index(’aderezado’, ’’) = 1
index(’aderezado’, ’’, back=.true.) = 10
scan(’aderezado’, ’ae’) = 1
scan(’aderezado’, ’ae’, back=.true.) = 7
scan(’aderezado’, ’ea’) = 1
scan(’aderezado’, ’ea’, back=.true.) = 7
scan(’aderezado’, ’Ae’) = 3
scan(’aderezado’, ’Ae’, back=.true.) = 5
scan(’aderezado’, ’Af’) = 0
scan(’aderezado’, ’Af’, back=.true.) = 0
scan(’aderezado’, ’’) = 0
scan(’aderezado’, ’’, back=.true.) = 0
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
74 6.4 Funciones intrı́nsecas especı́ficas de arrays
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
elemento. Esto significa que, dada una matriz de n × n de elementos reales llamada A, la
matriz B de n × n definida por
B = exp ( A )
sum(array)
Devuelve un escalar que es la suma todos los elementos de array. El tipo y el
kind del escalar coincide con el de array.
sum(array, mask=expr. lógica)
Devuelve un escalar que es la suma de todos los elementos de array que cum-
plen la condición dada por expr. lógica. Si ningún elemento cumple la con-
dición lógica, devuelve un cero.
sum(matriz, dim=num)
Si num = 1, devuelve un vector cuyos elementos son la suma de las columnas
de la matriz. Si num = 2, devuelve un vector cuyos elementos son la suma de
las filas de la matriz.
sum(matriz, dim=num, mask=expr. lógica)
Si num = 1, devuelve un vector cuyos elementos son la suma de las columnas
de la matriz que cumplen la condición dada por expr. lógica. Si num = 2,
devuelve un vector cuyos elementos son la suma de las filas de la matriz que
cumplen la condición dada por expr. lógica.
sum ( A ) ! devuelve 9
sum (A , mask =( A >0)) ! devuelve 15
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
sum (A , mask =( A >20)) ! devuelve 0
sum (A , dim =1) ! devuelve (/7 , 1 , 1/)
sum (A , dim =2) ! devuelve (/4 , 5/)
sum (A , dim =2 , mask =( A >0)) ! devuelve (/6 , 9/)
sum (A , dim =2 , mask =( A >5)) ! devuelve (/0 , 6/)
product
product(array)
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
dot product(vector 1,vector 2)
Esta función devuelve el producto escalar de dos vectores conformes de datos numéri-
cos. El tipo de vector 1 y vector 2 no es necesario que sea coincidente. El resultado
sigue las reglas usuales de conversión aritmética.
matmul(array 1,array 2)
Esta función devuelve el producto de dos arrays con formas compatibles con las
reglas algebraicas. Al menos uno de los dos argumentos debe ser una matriz. El tipo
de array 1 y array 2 no es necesario que sea coincidente. El resultado sigue las
reglas usuales de conversión aritmética.
transpose(matriz)
Esta función devuelve la matriz transpuesta de matriz, con el mismo tipo y kind.
La matriz no es necesario que sea una matriz cuadrada.
maxval(array)
Devuelve un escalar que es el máximo de los elementos de array. El tipo y
el kind del escalar coincide con el de array, teniendo en cuenta que array no
puede ser de tipo complex.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
maxval(array, mask=expr. lógica)
Devuelve un escalar que es el máximo de los elementos de array que cumple
la condición dada por expr. lógica. Si ningún elemento cumple la condición
lógica, devuelve un número arbitrario, dependiente del procesador.
maxval(matriz, dim=num)
Si num = 1, devuelve un vector cuyos elementos son el máximo de cada una
de las columnas de la matriz. Si num = 2, devuelve un vector cuyos elementos
son el máximo de cada una de las filas de la matriz.
maxval(matriz, dim=num, mask=expr. lógica)
maxval ( U ) ! devuelve 4
maxval (U , mask =( U <0)) ! devuelve -5
maxval ( A ) ! devuelve 6
maxval (A , mask =( A <5)) ! devuelve 3
maxval (A , dim =1) ! devuelve (/6 , 5 , 3/)
maxval (A , dim =2) ! devuelve (/5 , 6/)
maxval (A , dim =1 , mask =( A <0)) ! devuelve (/ -1200 , -4 , -2/)
maxloc — minloc
maxloc(vector)
Devuelve un vector de un elemento que es la posición (no el ı́ndice) que ocupa el
mayor elemento del vector. En caso de que haya varios máximos, solo devuelve
la posición del primero de ellos.
maxloc(vector, mask=expr. lógica)
Devuelve un vector de un elemento que es la posición (no el ı́ndice) que ocupa
el mayor elemento del vector que cumple la condición dada en expr. lógica.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
78 6.4 Funciones intrı́nsecas especı́ficas de arrays
En caso de que haya varios máximos, solo devuelve la posición del primero de
ellos. Si ningún elemento cumple la condición lógica devuelve el vector cero.
maxloc(matriz)
Devuelve un vector de dos elementos que es la posición (no los ı́ndices) que
ocupa el mayor elemento de la matriz. En caso de que haya varios máximos,
solo devuelve la posición del primero de ellos, considerando que la matriz se
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
recorre por columnas.
maxloc(matriz, mask=expr. lógica)
Devuelve un vector de dos elementos que es la posición (no los ı́ndices) que
ocupa el mayor elemento de la matriz que cumple la condición dada en expr.
lógica. En caso de que haya varios máximos, solo devuelve la posición del
primero de ellos, considerando que la matriz se recorre por columnas. Si ningun
elemento cumple la condición lógica devuelve el vector cero.
all(expr. lógica)
Devuelve la constante literal .true. si todos los elementos del array verifican la
condición expr. lógica, y la constante .false. si alguno los elementos del array
no la verifica.
Si el array es una matriz, se puede utilizar el argumento opcional dim para especificar
si se evalúan las columnas (dim=1) o las filas (dim=2). En ese caso el resultado es
un vector.
any(expr. lógica)
Devuelve la constante literal .true. si algún elemento del array verifica la condición
expr. lógica, y la constante .false. si ninguno de los elementos del array la
verifica.
Si el array es una matriz, se puede utilizar el argumento opcional dim para especificar
si se evalúan las columnas (dim=1) o las filas (dim=2). En ese caso el resultado es
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
un vector.
count(expr. lógica)
Devuelve un dato de tipo integer que cuenta el número de elementos del array que
verifican la condición expr. lógica.
Si el array es una matriz, se puede utilizar el argumento opcional dim para especificar
si se evalúan las columnas (dim=1) o las filas (dim=2). En ese caso el resultado es
un vector.
size(array)
Devuelve un escalar de tipo integer igual al número total de elementos de
array.
size(matriz, dim=num)
Si num = 1, devuelve un escalar igual al número de filas de la matriz. Si num
= 2, devuelve un escalar igual al número de columnas de la matriz.
shape(array)
Devuelve un vector de tipo integer con tantos elementos como dimensiones tiene
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
array, que contiene el número de elementos que hay en cada dimensión de array.
lbound
lbound(array)
Devuelve un vector de tipo integer, con tantos elementos como dimensiones
tiene array, que contiene el lı́mite inferior de cada una de las dimensiones de
array.
lbound(matriz, dim=num)
ubound
ubound(array)
Devuelve un vector de tipo integer, con tantos elementos como dimensiones
tiene array, que contiene el lı́mite superior de cada una de las dimensiones de
array.
ubound(matriz, dim=num)
Si num = 1, devuelve un escalar igual al lı́mite superior de las filas de la matriz.
Si num = 2, devuelve un escalar igual al lı́mite superior de las columnas de la
matriz.
reshape(vector 1,vector 2)
Esta función construye un array con la forma dada por el vector vector 2 y los
datos contenidos en vector 1.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
program main
integer :: n
integer :: U (2)
integer :: V (1)
real :: T (10:12)
integer :: A (2 ,3)
integer :: B (0:10 ,4:8)
real :: Zt (0:2 ,3)
integer :: Vu (2)
integer :: C (6)
! Funcion size
n = size ( T ) ! n = 3
n = size ( A ) ! n = 6
n = size (A , dim =1) ! n = 2
n = size (A , dim =2) ! n = 3
n = size ( B ) ! n = 55
n = size (B , dim =1) ! n = 11
n = size (B , dim =2) ! n = 5
n = size ( Zt ) ! n = 9
n = size ( Zt , dim =1) ! n = 3
n = size ( Zt , dim =2) ! n = 3
! Funcion shape
V = shape ( T ) ! V = (/3/)
U = shape ( A ) ! U = (/2 , 3/)
U = shape ( B ) ! U = (/11 , 5/)
U = shape ( Zt ) ! U = (/3 , 3/)
! Funcion lbound
V = lbound ( T ) ! V = (/10/)
U = lbound ( A ) ! U = (/1 , 1/)
n = lbound (A , dim =1) ! n = 1
n = lbound (A , dim =2) ! n = 1
U = lbound ( B ) ! U = (/0 , 4/)
n = lbound (B , dim =1) ! n = 0
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
82 6.4 Funciones intrı́nsecas especı́ficas de arrays
! Funcion ubound
V = ubound ( T ) ! V = (/12/)
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
U = ubound ( A ) ! U = (/2 , 3/)
n = ubound (A , dim =1) ! n = 2
n = ubound (A , dim =2) ! n = 3
U = ubound ( B ) ! U = (/10 , 8/)
n = ubound (B , dim =1) ! n = 10
n = ubound (B , dim =2) ! n = 8
U = ubound ( Zt ) ! U = (/2 , 3/)
n = ubound ( Zt , dim =1) ! n = 2
n = ubound ( Zt , dim =2) ! n = 3
Vu = (/3 , 3/)
Cr = 4.0
Zt = reshape ( Cr , Vu )
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Índice
7.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
7.2. Datos array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
83
7.1. Introducción
Hoy en dı́a el uso de objetos compuestos en Fortran se considera una práctica ha-
bitual tanto por la sencillez de su manejo como por la compacidad de su notación. Para
los arrays en particular, se ha visto que Fortran posee un conjunto de funciones intrı́nse-
cas que los dotan de una potencia de cálculo superior a la de cualquier otro lenguaje de
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
programación. En el caso de las estructuras, el poder representar de forma compacta un
objeto (una figura geométrica, una agenda personal, etc) ha permitido en los últimos años
un estilo de programación mucho más claro y estructurado.
Aunque los objetos compuestos ya han sido definidos y parcialmente estudiados, en
este capı́tulo vamos a desarrollar algunos aspectos tı́picos de su manejo que, por cuestiones
de claridad en la exposición, no se han desarrollado anteriormente.
En particular, en el caso de los arrays vamos a estudiar dos puntos de gran interés,
2. La asignación dinámica de memoria. ¿Es posible declarar un array del cual se sabe
cuántas dimensiones tiene, pero no cuáles son sus lı́mites?
De los datos de tipo derivado nos vamos a ocupar de dos cuestiones que, aunque son
sencillas, generalmente dan lugar a confusión,
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
inicial o final, se consideran los valores correspondientes a la declaración del array. Si se
omite el incremento, se considera que vale 1.
nombre ([ ini_1 ]:[ fin_1 ][: inc_1 ] ,[ ini_2 ]:[ fin_2 ][: inc_2 ] ,...)
V = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
11 12 13 14 15 16 17 18
21 22 23 24 25 26 27 28
31 32 33 34 35 36 37 38
declarados como
integer :: V (0:10)
integer :: A (6 ,8)
V = ( 0 , 1, 2 , 3, 4 , 5, 6 , 7, 8 , 9, 10 )
V = (0, 1, 2, 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 )
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
86 7.2 Datos array
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
61 62 63 64 65 66 67 68
A(2:5,7:7) (matriz de 4 × 1)
11 12 13 14 15 16 17 18
21 22 23 24 25 26 27 28
31 32 33 34 35 36 37 38
A=
41 42 43 44 45 46 47 48
51 52 53 54 55 56 57 58
61 62 63 64 65 66 67 68
program main
integer :: V (0:10)
integer :: A (6 ,8)
integer :: Uf (4)
integer :: Uc (5)
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
integer :: B (4 ,5)
integer :: U (4)
integer :: vW (4)
integer :: mW (1 ,4)
.
.
Uf = (/2 , 1 , 5 , 1/)
Uc = (/3 , 6 , 2 , 4 , 3/)
U = V ( Uf )
B = A ( Uf , Uc )
23 26 22 24 23 22
U = (1, 0, 4, 0)
13 16 12 14 13
21
B=
53 56 52 54 53
mW =
vW = (22, 21, 25, 21)
25
13 16 12 14 13 21
1.- Si el tamaño prefijado excede el número de valores que se van a almacenar, esta-
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
mos reservando memoria para elementos que luego no se van a utilizar.
2.- Si, por el contrario, el tamaño prefijado es menor que el número de valores que
se van a utilizar, el programa dará un error de ejecución.
Para evitar estos inconvenientes, Fortran permite asignar memoria a ciertos arrays,
llamados dinámicos, en tiempo de ejecución. Es decir, durante la ejecución, por medio de
una sentencia, se especifican las dimensiones que va a tener el array y se reserva la cantidad
de memoria necesaria para el mismo, siempre que en ese momento haya espacio suficiente
en la memoria de cálculo del procesador. Si por razones del algoritmo es necesario variar
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 7.2 Asignación dinámica de memoria
program main
real , allocatable :: U (:)
real , allocatable :: A (: ,:)
integer :: n
integer :: m
integer :: Ierr
.
.
write (* ,*) ’ Introducir la dimension del vector ’
read (* ,*) n
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
90 7.2 Datos array
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
program main
real , allocatable :: U (:)
integer :: n
integer :: NumCasos
integer :: i
integer :: Ierr
.
do i =1 , NumCasos
.
Si en alguno de los casos resulta que n toma un valor no positivo, el programa sigue
funcionando con normalidad sin tener que haber añadido lı́neas de código extra.
Si se definen secciones de un array y en algún momento el lı́mite inferior especificado
para una dimensión supera al superior, el subarray resultante es de tamaño cero. Esto
ocurre en el siguiente ejemplo donde el lı́mite inferior de la sección está dado en función
del contador del bucle, i, de modo que cuando éste adquiere el valor n-1 la sección definida
es un array de tamaño cero.
program main
integer , parameter :: n = 20
real :: U ( n )
real :: a
integer :: i
.
do i =1 , n
.
U ( i +2: n ) = a *0.5
.
end do
end program main
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
No hay que confundir la situación anterior con el error que se comete cuando en una
sección se establece un lı́mite inferior o superior fuera del rango de los lı́mites establecidos
en la declaración del array.
program main
integer , parameter :: n = 20
real :: U ( n )
real :: a
integer :: i
Se debe resaltar el hecho de que dos arrays de tamaño cero pueden tener el mismo
rango pero distinta forma, por ejemplo uno puede ser (0,2) y el otro (2,0), con lo que
no son conformes y, por tanto, no pueden ser operandos de la misma expresión. Al igual
que todo array, un array de tamaño cero es conforme con cualquier escalar.
ambos datos deben ser del mismo tipo. En Fortran, de forma general, existe la posibilidad
de definir funciones y operadores. Esta posibilidad se puede extender al caso de operandos
de tipo derivado lo que amplı́a el conjunto de operaciones que se pueden realizar con ellos.
Sin embargo, este tipo de operaciones se sale del propósito del presente curso.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Un tipo derivado puede tener como componentes datos de tipo array. En la definición
de un tipo derivado con una componente array, ésta debe ser declarada con la forma
totalmente especificada. Es decir, una componente de tipo array no puede ser declarada
con el atributo allocatable.
En la figura 7.3 se muestra un ejemplo de array como componente de una estructu-
ra, cumpliendo las limitaciones anteriormente descritas. Además, para hacer hincapié en
el hecho de que son dos conceptos distintos, hemos declarado un vector dinámico de es-
tructuras. Como todo array dinámico, antes de definirlo, hay que alocatarlo (fijar sus
dimensiones y reservar memoria). Una vez utilizado, y antes de finalizar el programa, hay
mientras que para acceder al elemento j−ésimo de una componente del elemento i−ésimo
del array de estructuras, se utiliza la expresión
nombre_array ( i) % componente ( j )
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 7.3 Array como componente de un tipo derivado
program main
integer , parameter :: numnotas = 3
type alumno
character ( len =15) :: nombre
character ( len =30) :: apellidos
real :: nota ( numnotas )
real :: media
end type alumno
type ( alumno ) , allocatable :: clase (:)
do i =1 , n
write (* ,*) ’ Nombre y apellidos del alumno ’, i
read (* ,*) clase ( i) %nombre , clase ( i) % apellidos
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
94 7.3 Datos de tipo derivado
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
estructura con una componente de tipo derivado, y por otra, el hecho de que el nombre
de la componente de una estructura puede coincidir con el nombre de un dato sin que
dé lugar a confusión, ya que se utilizan de forma completamente distinta.
program main
type punto
real :: x
real :: y
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
real :: z
end type punto
type circulo
type ( punto ) :: centro
real :: radio
end type circulo
type ( punto ) :: P
type ( punto ) :: centro
P %x = 1.0
P %y = 1.0
P %z = 1.0
c1 %centro %x = 1.0
c1 %centro %y = 2.0
c1 %centro %z = 3.0
c1 %radio = 25.0
97
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
98 8.1 Introducción
8.1. Introducción
El objeto de las operaciones de entrada y salida es transferir o recibir datos desde un
medio externo (cinta, disco magnético u óptico, pantalla, teclado). La lectura de datos es
una operación de entrada y la escritura de datos es una operación de salida. Un registro es
un conjunto de datos compuesto por campos que constituyen las unidades de información
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
más pequeñas e indivisibles. Se denomina fichero a un conjunto de registros contenidos
en la misma unidad.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
1) Abrir el fichero (open)
2) Escribir el fichero (write)
3) Cerrar el fichero (close)
Un fichero puede abrirse y cerrarse varias veces a lo largo del programa. Solo hay
que tener la precaución de respetar dos normas lógicas, no se puede cerrar un fichero que
no esté abierto y, no se puede abrir un fichero que no esté cerrado.
print * , lista_de_variables
read * , lista_de_variables
Si se desea dejar una lı́nea en blanco en la salida por pantalla, basta con poner
print *
unit=u
u es un dato simple o una constante entera positiva. A cada fichero se le asigna una
unidad que viene determinada por este número de forma que, a partir de este punto,
nos podemos referir al fichero en cuestión solo a través de su unidad sin tener que
especificar su nombre. Hay que tener en cuenta que,
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Si la unidad va a ser el primer especificador, se puede omitir la palabra clave
unit.
• No se puede asignar la misma unidad a dos ficheros distintos, si se van a utilizar
simultáneamente.
file=nombre
nombre es el nombre del fichero que se va a abrir. El nombre se puede dar en forma
de constante literal o de dato de tipo character
status=estado
estado es una constante literal o un dato de tipo character que puede tomar
cualquiera de los siguientes valores:
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
En algunos procesadores el especificador status es opcional en cuyo caso su valor
por defecto es unknown.
action=accion
accion es una constante literal o un dato de tipo character que puede tomar
cualquiera de los siguientes valores:
read el fichero que vamos a abrir se va a utilizar exclusivamente para leer, por lo
que si se intenta utilizar para escribir, dará un error de compilación.
write el fichero que vamos a abrir se va a utilizar exclusivamente para escribir, por
lo que si se intenta utilizar para leer, dará un error de compilación.
En los ejemplos anteriores hemos utilizado el orden habitual en el que se suelen poner
los especificadores. Si bien este orden se puede alterar, recordando que para cambiar de
lugar la unidad es obligatoria la palabra clave, lo recomendable es no hacerlo.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
102 8.3 Manejo de ficheros
unit=u
u es un dato o una constante entera positiva que especifica el fichero del que se va
a leer o escribir
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
unit
• Si los datos se van a leer del teclado o escribir en la pantalla, en vez de unit=u
se pone un asterisco (*).
fmt=’(form1,form2,...)’
’(form1,form2,...)’ es la lista de formatos con los que se va a leer o escribir los
datos. En la mayorı́a de los casos, si no se conoce el formato o los datos no poseen
un formato fijo, se pone un asterisco (*). En la sección 8.5 se desarrolla con más
detalle el uso de los formatos. Aunque en esta descripción estamos dando la lista de
iostat=v
Es posible que mientras leemos o escribimos un fichero se produzca un error. Por
ejemplo, nos encontramos con un dato que no tiene el formato especificado, o el
fichero no tiene tantas filas como creı́amos, etc. También puede ocurrir que queramos
leer un fichero de datos del que ignoramos el número total de registros que contiene.
El argumento iostat sirve para controlar este tipo de incidencias. v es una variable
entera que puede tomar los siguientes valores: v>0 si detecta un error de lectura o
escritura, v<0 si se alcanza el final del fichero durante la lectura y v=0 si la ejecución
es correcta. Este argumento es opcional.
lista vbles
Es la lista de variables, separadas por comas, en las que se van a cargar los datos
que se van a leer, o cuyos valores se van a escribir.
• Si se desea leer un registro, vacı́o o no, sin asignar ninguno de sus campos a
variables del programa, basta con poner
read (u ,*)
write (u ,*)
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
8.3.3. Sentencia close
La estructura general es,
unit=u
u es un dato o una constante entera positiva que especifica el fichero que se va a
cerrar
status=estado
estado es una constante literal o un dato de tipo character que puede tomar
cualquiera de los siguientes valores:
rewind ( unit = u )
rewind ( u )
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
backspace ( unit = u )
unit=u
u es un dato o una constante entera positiva que especifica la unidad del fichero
actual.
x = 3.0 x = 3.000
x = 3. x = 0.3 e +1
x = 3 e0 x = 3.0 e +0
x = 30 e -1 x = 30.0 e -1
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 8.1 Visualización del mismo fichero (a) sin formato y (b) con formato
(a) (b)
3.0 -0.145 2.34 3.000 -0.145 2.340
5.29 0. -7.893 5.290 0.000 -7.893
-1.333 8.54 9.32 -1.333 8.540 9.320
In [. m ]
• n es una constante entera positiva que indica el número total de espacios que ocupa
la representación del valor de la variable (incluyendo el signo “−”, si lo hubiera).
• m es una constante entera positiva (menor o igual que n) que indica el número total
de dı́gitos que aparecen en la representación del valor de la variable (sin incluir el
signo “−”, si lo hubiera). Para completar el número de dı́gitos especificado rellena
con ceros a la izquierda. Este descriptor es opcional.
Fn . d
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
106 8.5 Especificaciones de formato
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
-203 I4 -203
25 I2 25
25 I4.4 0025
25 I7.3 025
-25 I7.3 -025
• n es una constante entera positiva que indica el número total de espacios que ocupa
la representación del valor de la variable (incluyendo el signo “−”, si lo hubiera, y
el punto “.”).
Especificación
En . d
• n es una constante entera positiva que indica el número total de espacios que ocupa
la representación del valor de la variable, incluyendo
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
◦ El punto “.”
◦ El signo de la exponencial (no es opcional)
◦ Los dı́gitos de la exponencial (un máximo de tres)
◦ La letra E de la exponencial, en el caso de que la exponencial tenga menos de
tres dı́gitos significativos
• d es una constante entera no negativa que indica el número total de decimales que
van a aparecer, tras redondear.
Especificación
En . dEm
• n es una constante entera positiva que indica el número total de espacios que ocupa
la representación del valor de la variable, incluyendo
• d es una constante entera no negativa que indica el número total de decimales que
van a aparecer, tras redondear.
• m es una constante entera no negativa que indica el número total de dı́gitos que van
a aparecer en la exponencial.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
34.12e5 E10.4 0.3412E+07 34.12d3 E8.4 *********
34.12e5 E9.4 .3412E+07 34.12d300 E10.4 0.3412+302
34.12e5 E8.4 ********* 34.12d300 E9.4 .3412+302
34.12e5 E8.2 0.34E+07 34.12e5 E9.4E1 0.3412E+7
34.12e5 E12.4 0.3412E+07 34.12e5 E8.4E1 .3412E+7
34.12d3 E10.4 0.3412E+05 34.12e5 E12.4E2 0.3412E+07
34.12d3 E9.4 .3412E+05 34.12e5 E12.4E4 0.3412E+0007
Especificación
ESn . d [ Em ]
1 ≤ |mantisa| < 10
A[n]
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• A significa que es una variable de tipo character.
• n es una constante entera positiva que indica el número total de espacios que ocupa
la representación del valor de la variable.
L[n]
• n es un entero positivo que indica el número total de espacios que ocupa la repre-
sentación del valor de la variable. En cualquier caso, la salida será o bien una T si
el valor de la variable es .true. o bien una F si el valor de la variable es .false.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
110 8.6 Especificación de un formato
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
8.6. Especificación de un formato
En las sentencias print, read y write hemos visto que existe un especificador para
dar el formato de las variables que se van a leer o escribir. La forma general es,
Especificación
siendo form1,form2,... los formatos de representación de las variables junto con posibles
formatos especiales, separados por comas.
Es muy importante tener en cuenta que n debe ser una constante literal entera
positiva, nunca el identificador de un dato. Sin embargo n puede ser mayor que el número
de datos que va a leer o escribir.
Otra forma de especificar el formato utiliza una variable de tipo character que
almacena la lista de formatos.
Vamos a ver un ejemplo. Tenemos un fichero de texto (d in.dat) con los siguientes
datos,
3 4
1.5 0.023 -1.2 24.5
1E-3 4.33 15. 0.
32. .24 -100. 10.0
Queremos leer este fichero y copiarlo en otro (d out.dat) de forma que todas las
variables reales tengan el mismo formato.
program fichero
implicit none
integer :: n , m
integer :: i
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
integer :: unitID
real , allocatable :: A (: ,:)
unitID = 15
open ( unit = unitID , file = ’ d_in . dat ’ , status = ’ old ’ , action = ’ read ’)
allocate ( A (n , m ))
do i =1 , n
open ( unit = unitID , file = ’ d_out . dat ’ , status = ’ unknown ’ , action = ’ write ’)
deallocate ( A )
end program fichero
3 4
1.500 0.023 -1.200 24.500
0.001 4.330 15.000 0.000
32.000 0.240 -100.000 10.000
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• La estructura de un namelist dentro del fichero es la siguiente
& nombre_del_namelist
nombre_variable1 = valor_variable1
nombre_variable2 = valor_variable2
.
nombre_variableN = valor_variableN /
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Para leer los valores de las variables del namelist dentro de la unidad de programa
que lo utiliza, la secuencia es la siguiente
&Tiempo
horas = 12
minutos = 30
segundos = 15
am pm = ’PM’ /
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
114 8.7 Sentencia namelist
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 8.2 Ejemplo de fichero namelist
program main
integer :: horas
integer :: minutos
integer :: segundos
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Índice
9.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
9.2. Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
115
9.1. Introducción
La programación modular es una técnica de programación que consiste en dividir un
programa en partes bien diferenciadas, llamadas unidades de programa, que pueden ser
analizadas y programadas por separado. Se distinguen tres tipos de unidades de programa:
programa principal, función y subrutina. A estos dos últimos también se les llama de forma
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
genérica subprogramas.
Una unidad de programa se puede definir como un conjunto de instrucciones lógi-
camente enlazadas. A cada unidad de programa se le asigna un nombre, elegido por el
programador, para poder identificarlo. Cuando en un punto de una unidad de programa
se llama a ejecutar un subprograma, dicha unidad le cede el control para que se ejecuten
todas sus instrucciones. Finalizado el mismo, el control se devuelve al punto de la unidad
de programa llamadora, y se continúa con la ejecución de la instrucción siguiente a la que
realizó la llamada. El orden de ejecución se muestra en las figuras 9.1 y 9.2.
• Solo puede existir una unidad de programa principal, llamado programa principal,
que es el encargado de controlar y relacionar a todos los demás. Esta unidad de
programa debe indicar la solución completa del problema.
• Cada unidad de programa solo puede tener un punto de entrada y otro de salida.
• Una unidad de programa debe representar por sı́ misma una estructura lógica cohe-
rente y resolver una parte bien definida del problema.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 9.1 Diagrama de flujo de la programación modular
✬ ✩
program nombre
✫ ✪
❄ ✬ ✩ ✬ ✩
q q q
❄ ❄ ❄
q q q
❄ ✬ ❄ ✩✬ ❄ ✩
q
❄
q
✬ ❄ ✩
• Los programas son más sencillos de escribir y depurar, pues se pueden hacer pruebas
parciales con cada una de sus unidades de programa.
• Un programa se puede ampliar fácilmente con solo diseñar las nuevas unidades de
programa necesarias.
• Un subprograma puede ser llamado varias veces desde la misma unidad de programa,
evitando la repetición de instrucciones ya escritas.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
118 9.1 Introducción
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
sentencias
end program nombre
• Subprogramas externos
Son aquellos cuya definición se encuentra fuera del cuerpo de cualquier otra unidad
de programa, tal y como se muestra en la figura 9.2
• Subprogramas internos
Son aquellos cuya definición se encuentra dentro de una unidad de programa
• Subprogramas module
Son aquellos cuya definición se encuentra dentro de un unidad module
9.2. Funciones
Una función es un subprograma que, indicándole desde la unidad de programa lla-
madora los datos de entrada (argumentos) con los que se desea que realice los cálculos,
devuelve un único resultado.
Para entender este concepto pensemos en el caso más sencillo: las funciones intrı́nse-
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
cas con un único argumento. Por ejemplo, en el programa
program main
real :: x
real :: y
write (* ,*) x
end program main
estamos llamando a la función abs con la variable x del programa principal de la que
queremos conocer su valor absoluto. Una vez ejecutada la función, ésta devuelve un único
resultado al programa, el valor absoluto del dato de entrada, que en este ejemplo se utiliza
para asignarlo a la variable x.
Imaginemos ahora que no existe la función intrı́nseca abs y, dada la utilidad de la
misma, queremos crearla nosotros. Para ello programamos una función, que trataremos
como subprograma externo, y escribimos el siguiente código (definición de la función)
Como el programa principal, única unidad de programa conocida hasta este capı́tulo,
la estructura general de un subprograma función consta de (Fig. 9.4)
1 function valor_abs ( x )
2 real , intent ( in ) :: x
3 real :: valor_abs
4
5 valor_abs = x
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
6 if ( valor_abs < 0.0) valor_abs = - valor_abs
7
• Las sentencias de ejecución, entre las que siempre tiene que aparecer la sentencia
que define el resultado de la función.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Un punto de salida (lı́nea 8 de la figura 9.4), en la que se indica que ha terminado
la ejecución del programa y se ordena que el control pase a la unidad de programa
llamadora.
program main
interface
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
122 9.2 Funciones
interface
cuerpo_de_interface
end interface
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
2. Declaración de los argumentos y del tipo de resultado por tratarse de una función.
function transf_signo (a , b )
real , intent ( in ) :: a
real , intent ( in ) :: b
real :: transf_signo
if ( b >= 0) then
transf_signo = abs ( a )
else
transf_signo = - abs ( a )
end if
end function transf_signo
program main
interface
function transf_signo (a , b )
real , intent ( in ) :: a
real , intent ( in ) :: b
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
real :: transf_signo
end function transf_signo
end interface
real :: x
real :: y
9.3. Subrutinas
Una subrutina es un subprograma que, indicándole desde la unidad de programa
llamadora los datos de entrada con los que se desea que realice los cálculos, proporciona
un conjunto de datos de salida a dicha unidad de programa. Tanto los datos de entrada
como los de salida constituyen los argumentos ficticios de una subrutina.
En la figura 9.8 se muestra la definición de una subrutina que, dado un ángulo en
radianes (argumento de entrada: theta), calcula los correspondientes grados, minutos y
segundos (argumentos de salida: deg, min, sec).
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
6
7 real :: pi
8 real :: resto
9
10 pi = acos ( -1.0)
11
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
1. El argumento theta está declarado con el atributo intent(in) ya explicado
anteriormente que indica que es un dato de entrada al subprograma.
2. Los argumentos deg, min y sec están declarados con el atributo intent(out)
que indica que son datos de salida del subprograma y, por tanto, no pueden
ser utilizados en el subprograma hasta que no se les asigne un valor dentro del
mismo.
En las lı́neas 7 y 8 se declaran las variables locales del subprograma. Como su nombre
indica se trata de datos que solo conoce este subprograma subroutine y que son
necesarios para la realización de los cálculos que en él se definen. Su funcionamiento
• Las sentencias de ejecución, entre las que siempre tienen que aparecer la sen-
tencias que definen los argumentos ficticios de salida declarados con el atributo
intent(out).
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
126 9.4 Tratamiento de argumentos
program main
interface
subroutine conversion ( theta , deg , min , sec )
real , intent ( in ) :: theta
real , intent ( out ) :: deg
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
real , intent ( out ) :: min
real , intent ( out ) :: sec
end subroutine conversion
end interface
real :: angle
real :: deg
real :: min
real :: sec
llamadora. Mención especial merecen los argumentos de tipo array, los de tipo derivado
y el uso de subprogramas como argumentos. En esta sección nos dedicaremos a abordar
en detalle estas cuestiones.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
de un subprograma, ya que Fortran trabaja con la posición de memoria ocupada por la
variable, y esta posición es común para un argumento verdadero y su correspondiente
argumento ficticio. Por esta razón una modificación en el valor de un argumento ficticio
queda automáticamente reflejada en el valor de su correspondiente argumento verdadero.
Sin embargo, la situación habitual en un código es que en ocasiones se requiera que algunos
de los argumentos de entrada modifiquen su valor y otros no.
Para evitar la posible confusión se usa el atributo intent que permite, en tiempo de
compilación, especificar si un argumento es de entrada o de salida o si puede ser modificado
o no. El atributo intent tiene tres opciones:
• intent(out)
Los argumentos declarados con este atributo no pueden ser utilizados dentro del
subprograma hasta que no se les asigne un valor dentro del mismo, aunque sus
correspondientes argumentos verdaderos estuviesen definidos en la unidad de pro-
grama llamadora. Si esto ocurriese, darı́a un error en tiempo de compilación.
• intent(inout)
Los argumentos declarados con este atributo tienen un valor a la entrada al subpro-
grama que puede ser modificado a lo largo del mismo, cambio que se refleja en sus
correspondientes argumentos verdaderos.
En el ejemplo de la figura 9.10 se muestran dos errores tı́picos por mal uso del
atributo intent. El primer error ocurre al intentar modificar el valor del dato a que ha
sido declarado como argumento solo de entrada. El segundo error se produce al intervenir
el dato c en una operación sin que esté previamente definido, lo que se debı́a haber hecho
por estar declarado con el atributo intent(out). El argumento b es de entrada y salida
luego su correspondiente argumento verdadero modifica el valor que tenı́a antes de la
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
llamada, por el valor resultante de los cálculos realizados en el subprograma.
subroutine ejemplo (a , b , c )
real , intent ( in ) :: a
real , intent ( inout ) :: b
real , intent ( out ) :: c
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
call ejemplo (x , y , z ) ! Correcta
call ejemplo ( a =x , b =y , c = z ) ! Correcta
call ejemplo (x , c =z , b = y ) ! Correcta
call ejemplo ( b =y , a =x , z ) ! Incorrecta
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
130 9.4 Tratamiento de argumentos
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
total = 0.0 ! Valor por defecto
if ( present ( a )) then
total = a
if ( present ( b )) then
total = total + b
end if
else if ( present ( b )) then
total = b
end if
end subroutine suma
program main
interface
subroutine suma (a , b , total )
real , intent ( in ) , optional :: a
real , intent ( in ) , optional :: b
real , intent ( out ) :: total
end subroutine suma
end interface
real :: a = 2.0
real :: b = 5.0
real :: total
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Una forma sencilla de evitar este problema consiste en declarar el argumento ficticio
de tipo character con longitud asumida utilizando un asterisco como longitud,
subroutine explicita ( Ma , U )
real , intent ( in ) :: Ma (2 ,2)
real , intent ( in ) :: U (5)
.
end subroutine explicita
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 9.14 Argumento con forma explı́cita. Programa principal
1 program main
2 real :: A (2 ,2)
3 real :: B (2 ,3)
4 real :: z (5)
5 real :: t (6)
6 .
7 A = reshape ((/11 , 12 , 13 , 14/) , (/2 ,2/))
12 call explicita ( Ma =A , U = z )
13 call explicita ( Ma =B , U = t )
14 call explicita ( Ma = B (2 ,1) , U = t (2))
15 call explicita ( Ma =t , U = B )
16 call explicita ( Ma = B (2 ,2) , U = t (4))
17
En el ejemplo representado por las figuras 9.13 y 9.14, el programa principal define
los vectores y matrices
z = 41, 42, 43, 44, 45 ! !
11 13 21 23 25
A= B=
12 14 22 24 26
t= 51, 52, 53, 54, 55, 56
mientras que la subrutina siempre recoge una matriz Ma(2,2) y un vector U(5).
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• En la llamada de la lı́nea 12
!
11 13
Ma = U= 41, 42, 43, 44, 45
12 14
• En la llamada de la lı́nea 13
!
21 23
Ma = U= 51, 52, 53, 54, 55
22 24
• En la llamada de la lı́nea 14
!
22 24
• En la llamada de la lı́nea 15
!
51 53
Ma = U= 21, 22, 23, 24, 25
52 54
• En la llamada de la lı́nea 16
!
24 26
Ma = U= 54, 55, 56, 79, 85
25 −500
Un método más flexible de trabajar con argumentos con forma explı́cita consiste en
introducir las dimensiones como argumentos de entrada al subprograma, de esta forma el
argumento ficticio se adapta fácilmente a la forma del argumento verdadero (Figs. 9.15 y
9.16)
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
134 9.4 Tratamiento de argumentos
program main
integer , parameter :: n = 2
integer , parameter :: m = 3
real :: A (n , n )
real :: B (n , m )
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
real :: z (5)
real :: t (6)
.
A = reshape ((/11 , 12 , 13 , 14/) , (/2 ,2/))
B = reshape ((/21 , 22 , 23 , 24 , 25 , 26/) , (/2 ,3/))
z = (/41 , 42 , 43 , 44 , 45/)
t = (/51 , 52 , 53 , 54 , 55 , 56/)
subroutine asumida (M , U )
real , intent ( in ) :: M (: ,:)
real , intent ( in ) :: U (:)
.
end subroutine asumida
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 9.18 Argumento con forma asumida. Programa principal
1 program main
2 real :: A (2 ,2)
3 real :: B (2 ,3)
4 real :: z (5)
5 real :: t (6)
6 .
7 A = reshape ((/11 , 12 , 13 , 14/) , (/2 ,2/))
12 call asumida ( M =A , U = z )
13 call asumida ( M =B , U = t )
14 call asumida ( M = B (1:2 ,2:3) , U = t (2:4))
15 call asumida ( M = B (1:2 ,2:2) , U = t ((/1 ,3/)))
16
En el ejemplo representado por las figuras 9.17 y 9.18, el programa principal define
los vectores y matrices
z = 41, 42, 43, 44, 45 ! !
11 13 21 23 25
A= B=
12 14 22 24 26
t= 51, 52, 53, 54, 55, 56
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
M= U = 51, 52, 53, 54, 55, 56
22 24 26
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 9.19 Fichero con las funciones a integrar
function F ( x )
real , intent ( in ) :: x
real :: F
F = x * x + 3.0
end function F
function G ( x )
real , intent ( in ) :: x
real :: G
G = x * x - cos ( x )
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
138 9.4 Tratamiento de argumentos
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
7 end interface
8 interface
9 function G ( x )
10 real , intent ( in ) :: x
11 real :: G
12 end function G
13 end interface
14 interface
15 subroutine trapecio (F , a , b , integral )
16 interface
17 function F ( x )
28 real :: IntegralF
29 real :: IntegralG
30 real :: a
31 real :: b
32 .
33 a = 0.0
34 b = 5.0
35 call trapecio (F , a , b , IntegralF )
36 .
37 b = pi
38 call trapecio (G , a , b , IntegralG )
39 end program main
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
nombre del subprograma.
Por último hay que señalar que los únicos subprogramas válidos como argumentos
verdaderos son los subprogramas externos y los subprogramas module.
function F (n , x )
integer , intent ( in ) :: n
real , intent ( in ) :: x
real , dimension ( n ) :: F
integer :: i
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
do i =1 , n
F ( i ) = x ** i
end do
end function F
function Forz ( x )
real , intent ( in ) :: x (:)
real , dimension ( size ( x )) :: Forz
do i =1 , size ( x )
Forz ( i ) = x ( i )* x ( i )
end do
function Normaliza ( A )
real , intent ( in ) :: A (: ,:)
real , dimension ( size (A ,1) , size (A ,2)) :: Normaliza
real :: maximo
maximo = maxval ( A )
Normaliza = 0.0
if ( maximo /= 0.0) Normaliza = A / maximo
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 9.23 Programa principal para el uso de funciones arrays
program main
interface
function F (n , x )
integer , intent ( in ) :: n
real , intent ( in ) :: x
real , dimension ( n ) :: F
end function F
end interface
interface
function Forz ( x )
real , intent ( in ) :: x (:)
x = 5.0
U = F (n , x )
U = Forz ( U )
A = reshape (U , (/2 ,2/))
AN = Normaliza ( A )
end program main
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
142 9.6 Variables locales
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
◦ Está declarada con el atributo save
◦ Está inicializada en la lı́nea de declaración.
subroutine llamadas
integer , save :: NLLamadas = 0
integer :: Nl
do i =1 ,5
call llamadas
end do
end program main
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
programas internos y module. Sin embargo, en este punto conviene tener una idea global
del modo de expresar los subprogramas y cómo interactúan con la unidad de programa
llamadora. Esta unidad llamadora puede ser un programa principal u otro subprograma.
Por cuestiones de claridad, en los siguientes esquemas supondremos que la unidad
llamadora es el programa principal.
Subprograma externo
Un subprograma, function o subroutine, externo se caracteriza por las dos pro-
piedades:
Las figura 9.25 muestra un esquema de los puntos descritos anteriormente. Varios
subprogramas externos y un programa principal que los utiliza.
El uso habitual de este tipo de esquemas está limitado al caso sencillo en el que un
programa principal necesita a lo largo de su ejecución tan solo uno o dos subprogramas
que, bien porque son muy largos o bien porque se han extraı́do de alguna librerı́a, se
mantienen en ficheros independientes. Esto obliga a declarados explı́citamente con una
interface. Evidentemente, tener un programa con, exagerando un poco, 200 lı́neas de
interface, no es precisamente lo que se entiende por un programa claro y compacto.
Tampoco es muy habitual ver programas con varias interfaces anidadas. De nuevo,
la razón es la claridad en el estilo de programación.
function/subroutine nombre#1
..
.
end function/subroutine nombre#1
..
.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
function/subroutine nombre#r
..
.
end function/subroutine nombre#r
program nombre
interface
function/subroutine
.. nombre#1
.
end function/subroutine nombre#1
end interface ..
Subprograma interno
Un subprograma, function o subroutine, interno se caracteriza por las tres pro-
piedades:
1. Se encuentra dentro del esquema program — end program
2. Se encuentra justo antes de la sentencia end program
3. Se encuentra justo después de la sentencia contains
Las figura 9.26 muestra un esquema de los puntos descritos anteriormente. Varios
subprogramas internos contenidos en un programa principal.
El uso habitual de este tipo de esquemas está limitado al caso, también sencillo en el
que un programa principal necesita a lo largo de su ejecución unos pocos subprogramas,
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
todos ellos cortos en extensión y que probablemente estén relacionados entre sı́, en el
sentido de que algunos de ellos contengan llamadas a otros subprogramas del mismo
contains.
program nombre
..
.
contains
function/subroutine nombre#1
..
.
Subprograma module
Un subprograma module, function o subroutine, se caracteriza por las cuatro
propiedades:
Las figura 9.27 muestra un esquema de los puntos descritos anteriormente. Varios
subprogramas contenidos en un module y un programa principal que los utiliza.
El uso habitual de este tipo de esquemas se observa en los grandes programas que,
para resolver un problema importante deben resolver antes varios problemas intermedios.
La idea de este paradigma de programación consiste en manejar varios modules, cada uno
de ellos asociado a un problema completo en cuestión.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
146 9.7 Tipos de subprogramas
module nombre_module
..
.
contains
function/subroutine nombre#1
..
.
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
end function/subroutine nombre#1
..
.
function/subroutine nombre#r
..
.
end function/subroutine nombre#r
end module nombre_module
program nombre_program
Un primer vistazo a los esquemas presentados revela las diferencias entre un sub-
programa externo y otro de tipo interno o module.
En primer lugar, la forma de “declarar” la existencia del subprograma al programa
llamador. Si el subprograma es externo, necesitamos la construcción interface, que actúa
como una lı́nea más de declaración. Igual que para declarar un dato de tipo integer
usamos el esquema,
integer :: nombre_variable
para declarar una function externa de tipo real de una variable real utilizamos el
esquema
interface
function nombre_funcion ( arg )
real , intent ( in ) :: arg
real :: nombre_funcion
end function nombre_funcion
end interface
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
argumentos durante la compilación.
Variables locales
Son todas aquellas declaradas en los subprogramas internos que no son argumentos
ficticios. Una variable local solo es accesible para el propio subprograma interno que
lo contiene. Las variables locales de la figura 9.28 son:
• Para la función f, las variables i (lı́nea 18), z (lı́nea 19) y t (lı́nea 20)
• Para la función g, las variables i (lı́nea 29) y r (lı́nea 30)
Variables globales
Son todas aquellas declaradas en el programa principal. Una variable global es ac-
cesible, además de para el propio programa principal, para cualquier subprograma
interno a él siempre que no contenga una variable local con el mismo nombre. Las
variables globales de la figura 9.28 son: a, b, i, z, zf, zg (lı́neas 2 – 7)
1 program main
2 real :: a
3 real :: b
4 integer :: i
5 real :: z
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
6 real :: zf
7 real :: zg
8 .
9 zf = f ( a )
10 .
11 zg = g (a , b )
12 .
13 contains
14 function f ( x )
18 integer :: i
19 real :: z
20 real :: t
21 .
22 end function f
23
24 function g (x , y )
25 real , intent ( in ) :: x
26 real , intent ( in ) :: y
27 real :: g
28
29 integer :: i
30 real :: r
31 .
32 end function g
33 end program main
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
9.9. Subprograma module
La caracterı́stica principal de un subprograma module es que fı́sicamente su de-
finición está contenida dentro de una unidad module, siempre detrás de una sentencia
contains. Para desarrollar los conceptos relativos al alcance de las variables vamos a
ampliar el esquema representado en la figura 9.27 para introducir algunas variables en el
module y en los subprogramas.
Hay que hacer constar que vamos a utilizar un ejemplo concreto con tres subrutinas
(Fig. 9.29). En ella debemos distinguir los siguientes tipos de variables, según su alcance
Variables locales
Variables globales
Son todas aquellas variables declaradas antes de la sentencia contains, considerada
como zona de declaración del module. Una variable global es accesible para cualquier
subprograma contenido en el module siempre que él mismo no contenga una variable
local con el mismo nombre.
use nombre_del_module
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
150 9.9 Subprograma module
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
El ejemplo de los métodos de integración (figuras 9.32–9.34) pone de manifiesto
la comodidad del manejo de los subprograma module. En este caso estamos usando los
module como “cajones” para agrupar los subprogramas según su funcionalidad dentro del
problema a resolver. Ası́, hay un módulo que contiene todos los métodos de integración
implementados (Fig. 9.32) y otro módulo que contiene todas las funciones que hay que
integrar (Fig. 9.33). El programa principal (Fig. 9.34) accede a los contenidos de cada uno
de los módulos a través de la sentencia use.
Es importante observar que tanto la subrutina trapecio como la subrutina Simpson
mantienen la construcción interface – end interface para declarar el argumento ficticio
module CalculoMatrices
type sistema
real :: A (10 ,10)
real :: b (10)
real :: x (10)
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
end type sistema
contains
subroutine inversa (A , Ai )
real , intent ( in ) :: A (: ,:)
subroutine resuelve (A , b , x )
real , intent ( in ) :: A (: ,:)
real , intent ( in ) :: b (:)
real , intent ( out ) :: x (:)
type ( sistema ) :: Sistem10
.
end subroutine resuelve
end module CalculoMatrices
Figura 9.30
program main
use CalculoMatrices
integer , parameter :: n = 2
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
real :: A (n , n )
real :: InvA (n , n )
real :: detA
real , allocatable :: mA (: ,:)
type ( sistema ) :: Sist20
.
call inversa ( A =A , Ai = InvA )
.
call determinante ( A =A , det = detA )
Figura 9.31
program main
use CalculoMatrices , only : inversa , dimA
real :: A ( dimA , dimA )
real :: InvA ( dimA , dimA )
.
call inversa ( A =A , Ai = InvA )
.
end program main
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 9.32 Fichero con las subrutinas de los métodos de integración
module metodos
implicit none
contains
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348
154 9.9 Subprograma module
implicit none
contains
function F ( x )
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
real , intent ( in ) :: x
real :: F
F = x * x + 3.0
end function F
function G ( x )
real , intent ( in ) :: x
real :: G
G = x * x - cos ( x )
end function G
use funciones
use metodos
implict none
No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
❅
❅ x
y ❅ 0 1 2 3 4 5 6 7
❅
0 nul dle 0 @ P ‘ p
1 soh dc1 ! 1 A Q a q
2 stx dc2 ” 2 B R b r
3 etx dc3 # 3 C S c s
155
[ 2 ] Ellis T.M.R., Philips I.R., Lahey T.M. Fortran 90 programing. Addison-Wesley, 1994
[ 4 ] Metcalf M., Reid J., Cohen M. Fortran 95/2003 explained. Oxford University Press,
2004
[ 5 ] Nyhoff L.R., Leestma S.F. Fortran 90 for engineers & scientists. Prentice Hall, 1997
157
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-4584348