Informática I Alfonso Fidel Pons Funciones, Subrutinas y Tipo de dato Complejo Funciones Externas -Este tipo de Funciones devuelve un valor a través del identificador de la Función aunque puede devolver otros valores. Su sintaxis es: - Tipo FUNCTION Identificador (Lista de parámetros formales) acción1 acción2 ....... acciónn Identificador = Expresión ....... RETURN END -La llamada a una Función ha de formar parte de una sentencia siendo la sintaxis de la llamada la siguiente: -Identificador (Lista de parámetros actuales) EJEMPLO: program recursividad implicit none !variables integer x, factorial write(*,*)'Ingrese un entero positivo' read(*,*)x write(*,*)'El factorial de ',x,' es: ',factorial(x) end program recursividad integer recursive function factorial(n) if (n>1) then factorial=n*factorial(n-1) else factorial=1 endif return end function factorial Página 1 de 10 Informática I Alfonso Fidel Pons Subrutinas -Las Subrutinas empiezan con la sentencia SUBROUTINE -Puede devolver cero, uno o más valores siendo la transmisión por parámetros de cabecera. La ejecución termina con un fin lógico o RETURN siendo la última sentencia el fin físico o END. -Si sólo hay un RETURN se puede omitir porque END funcionar como si fuera RETURN. La sintaxis de las Subrutinas es: -SUBROUTINE Identificador (Lista de parámetros formales) acción1 acción2 ....... acciónn RETURN ....... END -El identificador del procedimiento ha de ser único, el primer carácter debe ser una letra. -En la Subrutina no se asocia un valor al identificador de la misma, devuelve los datos de salida modificando sus argumentos si son: -Nombres de variable. -Nombres de array. -Subrutinas ficticias. -El tipo de los argumentos se especifica explícita o implícitamente. LLAMADA A SUBRUTINAS -Una Subrutina puede ser invocada desde otra Subrutina o unidad de programa principal con la siguiente sintaxis: -CALL Identificador (Lista de parámetros actuales). -Los argumentos deben coincidir en orden y tipo con los argumentos ficticios de la Subrutina referenciada. La ejecución de CALL causa que el control de la ejecución pase a la Subrutina referenciada. -Los argumentos de CALL pueden ser: -Expresiones. -Arrays. -Subrutinas. Página 2 de 10 Informática I Alfonso Fidel Pons EJEMPLO: Práctica 5 - Problema 7 Realizar un algoritmo que reciba como datos los coeficientes a, b y c de una ecuación cuadrática y llame a un subalgoritmo RESOLVER para resolverla, para luego imprimir la ecuación con sus raíces correspondientes. Si no dispongo del tipo de datos COMPLEX program PROBLEMA7 implicit none ! Variables real:: a, b, c, x1r, x1i, x2r, x2i write(*,*) 'Ingrese los valores de los coeficientes de la ecuaci',char(162),'n de segundo grado' write(*,10) 10 FORMAT('a = ',$) !El $ es para que escriba en el mismo renglón read(*,*) a 20 write(*,20) FORMAT('b = ',$) read(*,*) b 30 write(*,30) FORMAT('c = ',$) read(*,*) c ! Invoco la subrutina con 7 parámetros para contemplar los complejos ! Podría usar menos parámetros dado que si las raíces son complejas, son conjugadas ! Por simplicidad x1r es la parte real de la x1 y x1i la imaginaria, idem con x2 if (a==0) then write(*,*) 'No es una cuadr',char(159),'tica' else call resolver(a, b, c, x1r, x1i, x2r, x2i) ! Para imprimir si alguna de las imaginarias es cero, las raices son reales if (x1i==0) then write(*,*) write(*,*) 'Ra',char(161),'ces reales' !char(161) es la 'í' write(*,50) x1r 50 FORMAT('X1 = ', f10.4) los cuales son decimales write(*,60) x2r 60 FORMAT('X2 = ', f10.4) los cuales son decimales else write(*,*) !f de float 10 espacios cuatro de !f de float 10 espacios cuatro de Página 3 de 10 Informática I Alfonso Fidel Pons write(*,*) 'Ra',char(161),'ces complejas conjugadas' !char(161) es la 'í' write(*,70) x1r, x1i 70 FORMAT('X1 = ', f10.4, '+ (', f10.4,'i)') write(*,80) x2r, x2i 80 FORMAT('X2 = ', f10.4, '+ (', f10.4,'i)') endif endif end program PROBLEMA7 subroutine resolver(a, b, c, x1r, x1i, x2r, x2i) real::a, b, c, x1r, x1i, x2r, x2i, disc disc = b**2 – 4* a * c if (disc==0) then x1r=-b/(2*a) x2r=x1r x1i=0 x2i=x1i endif if (disc<0) then !raíces complejas conj x1r=-b/(2*a) x2r=x1r x1i=sqrt(-disc)/(2*a) x2i=-x1i endif if (disc>0) then x1r=(-b + sqrt(disc))/(2*a) x2r=(-b - sqrt(disc))/(2*a) x1i=0 x2i=x1i endif end subroutine Página 4 de 10 Informática I Alfonso Fidel Pons Si dispongo del tipo de datos COMPLEX Solución simple program PROBLEMA7_simple implicit none real:: a, b, c complex::x1,x2 character::signo1, signo2 write(*,*) 'Ingrese los coeficientes' write(*,*)'Ingrese el valor del term. cuadrático:' read(*,*) a write(*,*)'Ingrese el valor del term. lineal:' read(*,*) b write(*,*)'Ingrese el valor del term. independiente:' read(*,*) c call resolver(x1, x2, a, b, c) write(*,*)x1 write(*,*)x2 end program PROBLEMA7_simple !En esta subrutina determino parámetros de entrada y salida subroutine resolver(x1, x2, a, b, c) real, INTENT(IN)::a, b, c !si modifico algún valor no compila complex, INTENT(OUT)::x1, x2 complex::disc !si declaro real da error la SQRT disc = b**2 - 4 * a * c x1=-b+sqrt(disc)/2/a x2=-b-sqrt(disc)/(2*a) return !Fin lógico end subroutine !Fin físico Solución mejorada program PROBLEMA7 implicit none ! Variables real:: a, b, c complex::x1,x2 character::signo1, signo2 write(*,*) 'Ingrese los valores de los coeficientes de la ecuaci',char(162),'n de segundo grado' write(*,10) 10 FORMAT('a = ',$) !El $ es para que escriba en el mismo renglón read(*,*) a do while (a==0) write(*,*) 'Ingrese un valor distinto de cero' write(*,11) 11 FORMAT('a = ',$) Página 5 de 10 Informática I Alfonso Fidel Pons read(*,*) a enddo 20 write(*,20) FORMAT('b = ',$) read(*,*) b 30 write(*,30) FORMAT('c = ',$) read(*,*) c ! Invoco la subrutina con 5 parámetros call resolver(x1, x2, a, b, c) !Impresión simple !El problema es que si las raices son reales las muestra !como complejas con parte imaginaria cero write(*,*)x1 write(*,*)x2 !Impresión mejorada write(*,*) if (AIMAG(x1)==0.0) then write(*,*)" Raices REALES" write(*,*)"X1= ",REAL(x1) write(*,*)"X2= ",REAL(x2) else write(*,*) " Raices complejas conjugadas" write(*,*) " X1= ", x1 write(*,*) " X2= ", CONJG(x1) write(*,*) write(*,*) " impresion mas elegante" if (AIMAG(x1)<0.0) then signo1='-' signo2='+' else signo1='+' signo2='-' endif write(*,*) " Raices complejas conjugadas" write(*,*) " X1= ", REAL(x1)," ",signo1,"j",ABS(AIMAG(x1)) write(*,*) " X2= ", REAL(x2)," ",signo2,"j",ABS(AIMAG(x2)) endif end program PROBLEMA7 subroutine resolver(x1, x2, a, b, c) idem anterior Página 6 de 10 Informática I Alfonso Fidel Pons Valor y referencia En los ejemplos anteriores los parámetros se pasan en forma predeterminada por referencia. Si un argumento se encierra entre paréntesis, implícitamente se está pasando por valor. Ejemplo planteado por Zenón ---------------------------------------------------------------------------------------------------------- Programa que muestra la diferencia entre las llamadas por valor y por referencia a una subrutina program Primero implicit none integer a,b ! Este programa es para probar argumentos por valor y por referencia ! armo una subrutina con dos argumentos formales ( x e y ) a los ! cuales simplemente se les suma 5 ! en la llamada hago las cuatro combinaciones posibles con los ! argumentos actuales con respecto a valor y referencia a=2 b=2 write(*,*)"Los dos por referencia" write(*,*)a,b call cambia(a,b) write(*,*)a,b a=2 b=2 write(*,*)"El primero por referencia y el segundo por valor" write(*,*)a,b call cambia(a,(b)) write(*,*)a,b a=2 b=2 write(*,*)"El primero por valor y el segundo por referencia" write(*,*)a,b call cambia((a),b) write(*,*)a,b a=2 b=2 write(*,*)"Los dos por valor" write(*,*)a,b call cambia((a),(b)) write(*,*)a,b write(*,*)"Fin" end program Primero subroutine cambia(x,y) integer x,y x=x+5 y=y+5 write(*,*)x,y end subroutine El programa produce la siguiente salida Los dos por referencia 2 2 (antes de la llamada) 7 7 (dentro de la subrutina) 7 7 (después de la llamada) El primero por referencia y el segundo por valor Página 7 de 10 Informática I Alfonso Fidel Pons 2 7 7 2 7 2 (antes de la llamada) (dentro de la subrutina) (después de la llamada) El primero por valor y el segundo por referencia 2 2 (antes de la llamada) 7 7 (dentro de la subrutina) 2 7 (después de la llamada) Los dos por valor 2 2 7 7 2 2 (antes de la llamada) (dentro de la subrutina) (después de la llamada) FIN Ejemplo planteado por Zenón ---------------------------------------------------------------------------------------------------Si se quiere hacer en forma explícita el pasaje por valor o por referencia debe ser indicado en la subrutina por medio de una directiva al compilador En el programa principal se invoca de la sig. manera: ……… ……… call resolver(%val(a), %val(b), %val(c), %ref(x1r), %ref(x1i), %ref(x2r), %ref(x2i)) ……… ……… En la subrutina subroutine resolver(a, b, c, x1r, x1i, x2r, x2i) !DEC$ ATTRIBUTES VALUE :: a, b, c !DEC$ ATTRIBUTES REFERENCE:: x1r, x1i, x2r, x2i real::a, b, c, x1r, x1i, x2r, x2i, disc ……… ……… end subroutine Entrada y salida En la solución simple del ejemplo de las raíces se realiza el pasaje de parámetros y se indica cómo serán considerados por el compilador. real, INTENT(IN)::a, b, c complex, INTENT(OUT)::x1, x2 INTENT (IN / OUT / INOUT) permite establecer si los parámetros son de Entrada, Salida o Entrada/Salida, independientemente de que se pasen por valor o por referencia. Si un parámetro es indicado como de Entrada a la subrutina, al pretender modificar su valor dentro de la misma, se produce un error en la compilación. Página 8 de 10 Informática I Alfonso Fidel Pons FUNCIONES INTRINSECAS CONCEPTO DE FUNCION -Son aquellas funciones incorporadas al compilador, que son accesibles desde un programa. Pueden ser llamadas en un programa dando el identificador de la Función seguido por sus argumentos entre paréntesis. -El formato de la Función será el siguiente: -Nombre (Identificador1, identificador2, ..., identificadorn). FUNCIONES ARITMETICAS -Son aquellas que realizan algún tipo de operación matemática. -Calcula el valor absoluto de un argumento real y devuelve un resultado real y positivo: -ABS (Expresión numérica) -Convierte un real a un entero truncándolo o eliminando la parte decimal devuelve un entero: -Var=INT (Expresión numérica). -NINT (Expresión numérica) (Realiza un redondeo). -Convierte un número entero a un real: -FLOAT (Expresión numérica). -Eleva un número real a la enésima potencia donde e es la base del logaritmo natural, devuelve un real: -EXP (Número). -Var=EXP (Número). -DEXP (Número) (Donde número es de doble precisión). -CEXP (Número) (Donde número es un número complejo). -Calcula el logaritmo natural de base e y es la inversa de la Función anterior, devuelve un real: -Var=LOG (Expresión numérica). -Calcula el logaritmo decimal o de base diez del argumento indicado, devuelve un real: -Var=LOG10 (Expresión numérica). -Calcula la raíz cuadrada del argumento indicado, devuelve un real: -Var=SQRT (Expresión numérica). -Calcula el módulo o resto de dos números, devuelve un entero: -MOD (Número1, número2). FUNCIONES TRIGONOMETRICAS -Son aquellas que realizan alguna operación con las razones de tipo trigonométrico. -Calcula el seno de una expresión dada, devuelve un real y debe estar entre 1 y -1: -Var=SIN (Expresión numérica) (Devuelve un real). -DSIN (Expresión numérica) (Devuelve un doble precisión). -CSIN (Expresión numérica) (Devuelve un complejo). -Calcula el coseno de una expresión dada, devuelve un real y debe estar entre 1 y -1: -Var=COS (Expresión numérica) (Devuelve un real). -DCOS (Expresión numérica) (Devuelve un doble precisión). -CCOS (Expresión numérica) (Devuelve un complejo). -Calcula la tangente de una expresión dada, devuelve un real: -Var=TAN (Expresión numérica) (Devuelve un real). -DTAN (Expresión numérica) (Devuelve un doble precisión). Página 9 de 10 Informática I Alfonso Fidel Pons -Calcula el arcoseno de una expresión dada, devuelve un real: -Var=ASIN (Expresión numérica). -Calcula el arcocoseno de una expresión dada, devuelve un real: -Var=ACOS (Expresión numérica). -Calcula el arcotangente de una expresión dada, devuelve un real: -Var=ATAN (Expresión numerica). -Calcula el seno hiperbólico de una expresión dada, devuelve un real: -Var=SINH (Expresión numérica). -Calcula el coseno hiperbólico de una expresión dada, devuelve un real: -Var=COSH (Expresión numérica). -Calcula la tangente hiperbólico de una expresión dada, devuelve un real: -Var=TANH (Expresión numérica). FUNCIONES DE NUMEROS COMPLEJOS -Toma la parte real de un argumento complejo: -REAL (Expresión compleja). -Toma la parte imaginaria de un argumento complejo: -AIMAG (Expresión compleja). -Calcula el conjugado de un argumento complejo: -CONJG (Expresión compleja). -Representa un argumento complejo tomado de números reales: -COMPLEX (Número1, número2). Página 10 de 10