Académique Documents
Professionnel Documents
Culture Documents
Elementos do Fortran 90
2.1 Introduo ca
Neste cap tulo vamos apresentar os elementos bsicos da linguagem de programao Fora ca tran 90. Como exemplo, vamos considerar o seguinte problema: escrever um programa que pergunte ao usurio as coordenadas x e y de trs pontos e que calcule a equao do a e ca c rculo que passa por esses trs pontos, a saber: e (x a)2 + (y b)2 = r2 e ento mostre as coordenadas (a, b) do centro do c a rculo e seu raio, r. Este problema problema aparentemente trivial, mas no to simples assim! O que e a e a ocorre se, por exemplo, os trs pontos fornecidos estiverem ao longo de uma reta? e
2.1.1
Anlise do problema a
Basicamente, a anlise consiste em criar um plano estruturado que envolva n a veis sucessivos de renamento at atingir um ponto em que o programador possa codicar cada e passo individual. Um exemplo de plano estruturado para o problema acima seria: a) Ler os trs conjuntos de coordenadas (x1, y1 ), (x2, y2 ), (x3, y3 ); e b) Resolver a equao do c ca rculo; c) Mostrar as coordenadas (a, b) e o raio r As partes a) e c) so triviais, mas a parte b) requer uma anlise mais aprofundada e ser a a a abordada no cap tulo 4. No momento, lanaremos mo de um recurso comum (alm de c a e util e importante) em programao, que mover b) para uma subrotina (procedimento ca e externo). Dessa forma, um poss vel cdigo em Fortran 90 estruturado de acordo com o o plano acima seria (arquivo circulo.f90)
11
PROGRAM circulo IMPLICIT NONE ! Esse programa calcula a equacao de um circulo passando por 3 ! pontos fornecidos pelo usuario . ! Utiliza - se da subrotina calcula_circulo ! Declaracao de variaveis REAL :: x1 , y1 , x2 , y2 , x3 , y3 , a , b , r ! Passo 1: le coordenadas PRINT * , " Entre com a coordenada dos tres pontos " PRINT * , " na ordem x1 , y1 , x2 , y2 , x3 , y3 " READ * , x1 , y1 , x2 , y2 , x3 , y3 ! Passo 2: chama subrotina calcula_circulo CALL calcula_circulo ( x1 , y1 , x2 , y2 , x3 , y3 ,a ,b , r ) ! Passo 3: escreve resultado na tela PRINT * , " O Centro do circulo que passa por esses & & pontos eh ( " ,a , " ," ,b , " ) " PRINT * , " Seu raio eh " ,r END PROGRAM circulo
2.2
Estrutura Bsica a
Um programa em fortran 90 tem a seguinte estrutura bsica: a PROGRAM nome IMPLICIT NONE [ parte de especifica ~ o ] ca [ parte de execu ~ o ] ca [ parte de subprogramas ] END PROGRAM nome
2.2.1
Parte de Especicao ca
REAL :: x1 , y1 , x2 , y2 , x3 , y3 , a , b , r Na parte de especicao, logo aps o IMPLICIT NONE, onde se faz a declarao de ca o e ca variveis (e outros tipos de declarao). Variveis so basicamente endereos lgicos a a ca a a c o trechos de memria onde uma determinada informao est armazenada. o ca a 12
Veremos adiante que o computador capaz de manipular diferentes tipos de variveis. e a Os tipos mais comuns so: a REAL :: DOUBLE PRECISION :: INTEGER :: CHARACTER :: LOGICAL :: COMPLEX :: O IMPLICIT NONE deve estar sempre presente! Ele fora o programador a declarar exc plicitamente todas as variveis, o que muito importante pois evita uma srie de poss a e e veis erros de programao. ca
2.2.2
Comentrios a
Linhas cujo primeiro caractere no branco ! so consideradas comentrios e so ignoradas a e a a a pelo compilador. Comentar bem o cdigo uma boa prtica. o e a
2.2.3
Parte de Execuo ca
PRINT * , " Entre com a coordenada dos tres pontos " PRINT * , " na ordem x1 , y1 , x2 , y2 , x3 , y3 " READ * , x1 , y1 , x2 , y2 , x3 , y3 ! Passo 2: chama subrotina calcula_circulo CALL calcula_circulo ( x1 , y1 , x2 , y2 , x3 , y3 ,a ,b , r ) Na parte de execuo esto todos os comandos que devem ser executados pelo compuca a tador (PRINT, READ, CALL, etc) e que perfazem o chamado algor tmo. Criar um algor timo numrico que seja representvel pelo conjunto de comandos dispon e a veis em uma determinada linguagem corresponde ao cerne do mtodo numrico. e e
2.2.4
Caractere de continuao ca
PRINT * , " O Centro do circulo que passa por esses & & pontos eh ( " ,a , " ," ,b , " ) " Se o ultimo caractere de uma linha for &, isso diz ao compilador que o comando continua na prxima linha. Ele usado em dois contextos: o e - Quebrar uma string de caracteres longa. Se o & estiver dentro de uma string de caracteres, ento deve haver outro & no inicio da linha seguinte; a - Quebrar linhas de cdigo, de forma a torn-lo mais legivel. Ex: o a CALL calcula_circulo ( x1 , y1 , x2 , y2 , x3 , y3 ,& ! quebrei a linha a ,b , r )
13
2.3
Compilando o cdigo o
Uma vez tendo o cdigo pronto, devemos compil-lo. Quando dizemos compilarum o a cdigo nos referimos, na verdade, a dois procedimentos distintos. o O primeiro (compilao propriamente dita) a anlise do cdigo pelo compilador, que ca e a o vai ler e analisar cada linha vlida de cdigo (i.e., linhas no vazias e que no comecem com a o a a !), procurando vericar se h algum erro de sintaxe. Quando isso ocorre, o compilador a retorna um ou mais erros de compilao. Por exemplo, o cdigo abaixo retornar um ca o a erro de compilao: ca PRINT , " Entre com a coordenada dos tres pontos " Os erros de compilao no tm grande consequncia, pois so facilmente detectados ca a e e a pelo compilador. J erros semnticos podem resultar em erros de execuo (diviso a a ca a por zero, por exemplo) ou simplesmente podem passar desapercebidos pelo compilador, gerando um resultado incorreto. Por exemplo, imaginemos um programa de computador capaz de analisar uma frase e vericar se a gramtica est correta. Se lhe fornecermos a frase O gato est sobre a a a o mesa, o programa certamente apontar o erro gramatical (o mesa). Entretanto, a se a frase analisada for A mesa est sobre o gato, o programa dir que a frase est a a a gramaticalmente correta, apesar de semanticamente no fazer sentido. a A segunda parte do processo chamada linking, em ingls. Nela, o compilador vai e e gerar o cdigo binrio que poder ser executado pelo compilador. o a a
2.4
Tipos de dados
Em matemtica, assim como em programao, h dois tipos bsicos de nmeros: os que a ca a a u so inteiros e os que no o so. a a a Em programao, a diferena entre esses dois tipos absolutamente vital, pois ca c e est ligada ` maneira como os nmeros so representados e armazenados na memria e a a u a o manipulados pelo processador. Isso ser visto em detalhes mais adiante (cap a tulo 3), no momento basta considerar que: - Uma varivel INTEGER um nmero inteiro, sempre armazenado de forma exata a e u na memria do computador, e tem um intervalo poss o vel de valores relativamente baixo, tipicamente entre -2,1 109 e 2,1 109 em um computador de 32 bits; - Um nmero REAL, por outro lado, armazenado como uma aproximao com um u e ca n mero xo de algarismos signicativos (7 ou 8) e tem um intervalo bem u maior, tipicamente entre -1038 e +1038 em um computador com 32 bits; - Um nmero DOUBLE PRECISION uma representao usando 64 bits com tipicamente u e ca 16 algarismos signicativos e um intervalo entre -10308 e +10308 . Existem vrias funes intr a co nsecas do Fortran que retornam as propriedades dos nmeros u que podem ser representados por um dado processador: EPSILON, HUGE, TINY, etc. Isso ser visto em detalhes no prximo cap a o tulo, mas o cdigo abaixo mostra como usar tais o funes para mostrar os limites da representao numrica em um dado computador (arco ca e quivo funcoes numericas.f90).
14
REAL :: x DOUBLE PRECISION :: y INTEGER :: i INTEGER *8 :: j PRINT * , & " O menor numero positivo que somado a 1 retorna numero maior & & que 1: " PRINT * , EPSILON ( x ) , EPSILON ( y ) PRINT * , & " O maior numero positivo que pode ser representado : " PRINT * , HUGE ( x ) , HUGE ( y ) , HUGE ( i ) , HUGE ( j ) PRINT * , & " O menor numero positivo que pode ser representado : : " PRINT * , TINY ( x ) , TINY ( y ) Sa do programa funcoes numericas.f90: da >>O menor numero positivo que somado a 1 retorna numero maior >> que 1: >> 1.1920929 E -07 2. 220446 049250313 E -016 >>O maior numero positivo que pode ser representado : >> 3.4028235 E +38 1. 797693 134862316 E +308 2147483647 9223372036854 >> 775807 >>O menor numero positivo que pode ser representado : >> 1.1754944 E -38 2. 225073 858507201 E -308 Saber os limites da represento numrica de um processador muito importante. Se a e e durante a execuo de um programa uma operao resultar em um nmero fora do limite ca ca u a ser representado, ocorre a chamada exceo de ponto utuante. O que acontece ca depois depende da forma como o programa foi compilado.
2.5
Expresses artimticas o e
Uma vez declaradas as variveis, pode-se atribuir valores a elas de vrias formas: a a - Usando o READ; - Atribuio direta. Ex: x = 2.2; ca - Atravs de uma expresso aritmtica. e a e Ex: a = b + c*d/e - f**g/h + i * j + k Os operadores aritmticos em Fortran so: e a + * / ** (exponenciao) ca 15
Um ponto de fundamental importncia que o Fortran executa as operaes acima de a e co acordo com as prioridades abaixo: 1. exponenciao; ca 2. multiplicao e diviso; ca a 3. adio e subtrao. ca ca Dentro do mesmo n de prioridade, a conta ser feita da esquerda para a direita, vel a com excesso da exponenciao, que feita da direita para a esquerda. Por exemplo, a ca e vamos estudar como o computador executa a seguinte expresso aritmtica: a e a = b + c * d / e - f ** g / h + i * j + k Os passos so: a 1. Calcula f**g e salva em temp1 2. Calcula c*d e salva em temp2 3. Calcula temp2/e e salva em temp3 4. Calcula temp1/h e salva em temp4 5. Calcula i*j e salva em temp5 6. Calcula b+temp3 e salva em temp6 7. Calcula temp6-temp4 e salva em temp7 8. Calcula temp7+temp5 e salva em temp8 9. Calcula temp8+k e salva em a. Em clculo numrico todo o cuidado pouco. Os exemplos a seguir ilustram os cuidaa e e dos que devem ser tomados para se evitar erros semnticos que podem resultar em erros a numricos. e
2.5.1
Exemplo 1
Qual o resultado do cdigo abaixo? o INTEGER :: i , j i = 1 j = 3 PRINT * , " Resultado = " , i / j >> Resultado = 0 Por qu? i e j so inteiros, portanto o que foi feito uma diviso entre nmeros e a e a u inteiros, cujo resultado um inteiro truncado. Outros exemplos: e 5/2 = 2, 10/3 = 3, 1999/1000 = 1, etc. 16
2.5.2
Exemplo 2
Qual o resultado do cdigo abaixo? o REAL :: x x = 1/3 PRINT * , " Resultado = " , x >> Resultado = 0.000000 Por qu? Para o compilador, nmeros sem o ponto (Ex: 1, 3) so inteiros. Dessa e u a forma o que foi feito foi uma diviso de inteiros que resultou em um inteiro que ento a a foi convertido em um nmero real. Importante: o computador sempre faz exatamento o u que lhe dito para fazer... e Para obter o resultado esperado, a sintaxe deveria ser: x = 1./3. ou x = 1.0/3.0 ... >> Resultado = 0.333333 ou x = 1. E0 /3. E0
2.5.3
Exemplo 3
Qual o resultado do cdigo abaixo? o REAL :: x x = 1/3. PRINT * , " Resultado = " , x >> Resultado = 0.333333 Por qu? Quando h diferentes tipos de dados em uma (sub)expresso, o compilador e a a promove um tipo para outro de acordo com a seguinte prioridade: 1 - INTEGER (baixa), 2 - REAL, 3 - DOUBLE, 4 - COMPLEX (alta) Assim, na expresso acima, o 1, sendo inteiro, foi promovido a real, e a expresso foi a a calculada entre dois reais.
2.5.4
Exemplo 4
Qual o resultado do cdigo abaixo? o REAL :: x , y INTEGER :: i , j i x y j = = = = 3.9 3.9 0.1 x+y
17
PRINT * , " Resultado = " , i , j >> Resultado = 3 4 Porque? Inteiros so sempre truncados em direo ao zero. No caso de j, a operao a ca ca de truncamento foi feita aps a execuo da expresso ` direita. o ca a a Para se obter o inteiro mais prximo, o Fortran tem uma funo espec o ca ca para isso: i = NINT (3.9) >> Resultado = 4
2.5.5
Exemplo 5
PRINT * , " Resultado = " , a a = c/d*b PRINT * , " Resultado = " , a >> Resultado = 90.000000 >> Resultado = 0.000000 Em clculo numrico no necessriamente valem vrias propriedades das operaes a e a a a co aritmticas em matemtica, tais como associatividade e distributiva (ver cap e a tulo 3). Em outras palavras, a ordem dos fatores altera o resultado!
2.6
Vimos atrs a funo dos comandos READ e PRINT. a ca REAL :: a , b INTEGER :: c READ * , a , b , c PRINT * , a , b , c O * signica que os dados impressos ou lidos sero formatados automaticamente de a acordo com a lista de variveis apresentadas (list-directed). O formato atribu depende a do do tipo da varivel a Ex: se a=1.1, b=2.2 e c=10, o PRINT acima retorna:
18
>>
1.100000
2.200000
10
O que ocorre se o input do programa for: 1.1 2.2 10.? Ocorre um erro, pois o programa est esperando que o terceiro nmero seja um nmero inteiro. a u u
2.7
Um procedimento uma seo especial de um programa que chamada, de alguma forma, e ca e sempre que necessrio. Procedimentos podem ser intr a nsecos (ou seja, parte do Fortran) ou escritos pelo programador ou por terceiros. H uma categorizao adicional, dependendo a ca da forma como esses procedimentos so usados: funes e subroutinas. a co Basicamente, o propsito de uma funo tomar um ou mais valores (ou argumentos) o ca e e criar um unico resutado. O Fortran tem inmeras funes intr u co nsecas: ! Argumento de funcoes trigonometricas devem estar em radianos ! SIN ( x ) LOG ( x ) LOG10 ( x ) SQRT ( x ) EXP ( x ) etc . Uma lista das funes intr co nsecas do Fortran 90 pode ser encontrada em http://www.nsc.liu.se/ boein/f77to90/a5.html.
2.8
Funes externas co
A sintaxe bsica para se criar uma funo externa no Fortran : a ca e < tipo > FUNCTION nome ( arg1 , arg2 , ... , argn ) IMPLICIT NONE [ parte de especifica ~ o ] ca [ parte de execu ~ o ] ca END FUNCTION nome
Funes so usadas/criadas por vrios motivos: co a a 1. Organizao do cdigo: programao modular; ca o ca 2. Evitar duplicao de cdigo (funes podem ser chamadas vrias vezes); ca o co a 3. Uso de cdigos de terceiros. o Vale lembrar que a losoa por trs dos procedimentos que o programa principal no a e a precisa saber nada sobre os detalhes internos do procedimento: compartimentalizao ca do cdigo. o
19
2.8.1
Exemplos
Funo que calcula a raiz cbica de um argumento (arquivo raiz cubica.f90). ca u REAL FUNCTION raiz_cubica ( x ) IMPLICIT NONE ! Declaracao do argumento da funcao REAL , INTENT ( in ) :: x ! Variaveis locais REAL :: log_x ! Calcula a raiz c bica usando logaritmos u log_x = LOG ( x ) raiz_cubica = EXP ( log_x /3.) END FUNCTION raiz_cubica Note que: - log x uma varivel interna, no vista pelo programa principal e a a e - o atributo INTENT(in) diz ao computador que a varivel x no pode ser modicada a a durante a execuo. ca Este outro exemplo mostra uma funo que l um valor de uma varivel inteira. Note ca e a que essa funo no tem argumento. ca a INTEGER FUNCTION le_valor () IMPLICIT NONE ! Le numero PRINT * , " Por favor entre um numero inteiro : " READ * , le_valor END FUNCTION le_valor Tal funo pode ser chamada pelo programa principal da seguinte forma, por exemplo: ca soma = le_valor ()* le_valor ()
2.9
Subrotinas
A diferena entre uma subroutina e uma funo est na forma como o programa se refere c ca a a ela e como os resultados (se houver) so retornados. a Subrotinas so acessadas pelo comando CALL, da seguinte forma: a CALL nome ( arg1 , arg2 , ...) 20
O CALL causa uma transferncia de controle para a subrotine, de forma que o e programa interrompido temporariamente e as instrues internas da subrotina so exee co a cutadas. A lista de argumentos de uma subrotina pode conter argumentos de entrada (input), de sa (output), ou nenhum argumento. A sintaxe bsica : da a e SUBROUTINE nome ( arg1 , arg2 , ... , argn ) IMPLICIT NONE [ parte de especifica ~ o ] ca [ parte de execu ~ o ] ca END SUBROUTINE nome No arquivo raizes.f90 encontra-se o exemplo abaixo, que uma subrotina que calcula e a raiz quadrada, cbica, qudrupla e qu u a ntupla de um nmero. u SUBROUTINE raizes (x , x2 , x3 , x4 , x5 ) IMPLICIT NONE ! Declaracao do input REAL , INTENT ( in ) :: x ! Declaracao do output REAL , INTENT ( out ) :: x2 , x3 , x4 , x5 ! Variaveis locais REAL :: log_x ! Calcula raiz quadrada x2 = SQRT ( x ) ! Calcula as outras raizes usando logaritmos log_x = LOG ( x ) x3 = EXP ( log_x /3.) x4 = EXP ( log_x /4.) x5 = EXP ( log_x /5.) END SUBROUTINE raizes Exemplo de programa que chama a subrotina raizes: PROGRAM exemplo IMPLICIT NONE REAL :: arg , raiz2 , raiz3 , raiz4 , raiz5 PRINT * , " Entre com valor do argumento : " READ * , arg ! Chama a subrotina CALL raizes ( arg , raiz2 , raiz3 , raiz4 , raiz5 ) 21
PRINT * , " Raizes = " , raiz2 , raiz3 , raiz4 , raiz5 END PROGRAM Rodando: >> Entre com valor do argumento : 10. >> Raizes = 3.162278 2.154435
1.778279
1.584893
Observao importante sobre subrotinas: a ordem, tipo e nmero de argumentos usados ca u no programa que chama a subrotina deve corresponder exatamente ao que foi denido na subrotina. Coisas imprevistas podem acontecer se isso no for obedecido! Por exemplo, a uma subrotina com os seguintes argumentos: SUBROUTINE teste (a ,b , c ) ... REAL :: a ,b , c ... chamada pelo seguinte programa: ... DOUBLE PRECISION :: a ,b , c ... CALL teste (a ,b , c ) ... resultar em erro. a Alm do INTENT(in) e INTENT(out), existe outro atributo que pode ser usado em e uma subrotina: dum = INTENT ( inout ) Esse argumento signica que a varivel dum pode ser usada tanto para passar quanto a receber informaes da subrotina. co O uso dos INTENT muito importante, como uma salvaguarda para erros de proe gramao. ca
2.10
O Fortran possui duas construes que podem ser usadas para tomadas de deciso durante co a o programa. So elas: IF e CASE. Antes de ver como us-las, vamos estudar um pouco a a sobre variveis LOGICAL e tambm sobre expresses lgicas. a e o o
22
2.10.1
As variveis lgicas so variveis de 1 bit apenas: 0 signica falso e 1, verdadeiro (na a o a a verdade 1 bit efetivamente utilizado, mas elas so armazenadas em palavras de 32 bits). e a Declarao: ca LOGICAL :: var1 , var2 , etc ... Para atribuir valores a elas, pode-se faz-lo diretamente: e var1 = . TRUE . var2 = . FALSE . ou atravs de expresses lgicas, que fazem uso dos chamados operadores relacionais: e o o > >= < <= == /= ! maior ! maior ou igual a ! menor ! menor ou igual a ! igual a ! diferente de e dos operadores lgicos: o . NOT . . AND . . OR . . EQV . . NEQV . ! nao logico ! e logico ! ou logico ! equivalencia logica ! nao equivalencia logica
Exemplos de expresses lgicas: o o var1 var2 var3 var4 var5 var6 = = = = = = 5 > 4 2 > 2 SQRT ( x ) > 1. . AND . SQRT ( x ) <= 2. a == b . OR . a /= c . NOT . ( a < b ) a == b . EQV . a /= c
2.10.2
A construo IF ca
As variveis e expresses lgicas so usadas em conjunto com a construo IF para permitir a o o a ca a tomada de decises ao longo de um programa. A forma bsica dessa construo o a ca e IF ( express~ o l gica 1) THEN a o comandos 1 ELSE IF ( express~ o l gica 2) THEN a o comandos 2 ELSE IF ( express~ o l gica 3) THEN a o 23
comandos 3 ELSE comandos 4 END IF O nmero de IFs depende da problema em questo, e pode ser apenas um. Nesse caso u a pode-se usar uma verso simplicada: a IF ( express~ o l gica 1) comando a o Como exemplo, vamos fazer um programa que: 1. Leia o nome de um aluno; 2. Leia as notas dos 4 EPs de AGA0503; 3. Leia as notas das duas provas; 4. Calcule a mdia nal; e 5. Escreva a mdia nal e se o aluno foi aprovado, reprovado ou cou em recuperao. e ca Uma poss soluo est no programa media final.f90: vel ca a PROGRAM media_final ! Programa que le o nome do aluno , as notas dos ! EPs e das provas , calcula a media final ! e diz se o aluno foi aprovado ou nao ! Usa a funcao le_valor IMPLICIT NONE ! Definicao de variaveis CHARACTER ( LEN =10) :: nome , situacao REAL :: EP1 , EP2 , EP3 , EP4 REAL :: P1 , P2 REAL :: media REAL , EXTERNAL :: le_valor ! Le nome do aluno PRINT * , " Digite o nome do aluno : " READ * , nome ! Le as notas dos EPs EP1 = le_valor ( " EP1 " ) EP2 = le_valor ( " EP2 " ) EP3 = le_valor ( " EP3 " ) EP4 = le_valor ( " EP4 " ) ! Le as notas das provas P1 = le_valor ( " P1 " ) 24
P2 = le_valor ( " P2 " ) ! Calcula a media final media = 0.4*( EP1 + EP2 + EP3 + EP4 )/4. + & 0.6*( P1 + P2 )/2. ! Determina situacao IF ( media < 3.) THEN situacao = " reprovado " ELSE IF ( media < 5) THEN situacao = " recuperacao " ELSE situacao = " aprovado " ENDIF ! Escreve resultado PRINT * , " O aluno " // TRIM ( nome )// " teve media = " , media PRINT * , " Sua situacao : " // situacao
END PROGRAM REAL FUNCTION le_valor ( oque ) IMPLICIT NONE CHARACTER ( LEN =3) , INTENT ( in ) :: oque ! Le numero PRINT * , " Digite a nota do " // oque // " : " READ * , le_valor END FUNCTION le_valor
2.10.3
SELECT CASE
Uma alternativa ao IF o CASE: e SELECT CASE ( express~ o ) a CASE ( seletor 1) comandos 1 CASE ( seletor 2) comandos 2 CASE ( seletor 3) comandos 3 ............. CASE ( seletor n ) comandos n CASE DEFAULT comandos padrao 25
END SELECT Exemplo: INTEGER :: mes SELECT CASE ( mes ) CASE (1:2) PRINT * , " Ferias de verao ! " CASE (3:6) PRINT * , " Aulas do primeiro semestre " CASE (7) PRINT * , " Ferias de inverno ! " CASE (8:11) PRINT * , " Aulas do segundo semestre " CASE DEFAULT PRINT * , " Acho que estamos em dezembro ... " END SELECT
2.11
Uma grande parte das tcnicas matemticas baseia-se em alguma forma de processo e a iterativo em que a soluo atingida atravs de passos sucessivos. ca e e Por exemplo, pode-se calcular o valor de atravs da srie e e 1 1 1 1 1 =1 + + + ... 4 3 5 7 9 11 (2.1)
Assim, para calcular usando a srie acima (o que, na verdade, seria uma pssima e e idia...), temos que somar os termos sucessivamente at atingirmos a preciso desejada. e e a Alm disso, o processamento de dados em geral requer que a mesma ao seja e ca aplicada repetidamente para cada dado. Assim, um dois mais importantes conceitos em programao a habilidade de repetir uma sequncia de comandos, seja um nmero preca e e u determinado de vezes seja at que determinada condio seja satisfeita. e ca
2.11.1
DO contador = inicial , final , [ incremento ] comandos END DO Notas: - O contador e os valores ` direita do = devem ser variveis ou expresses inteiras a a o - O incremento ao contador optativo e
26
- Quando o DO iniciado, o n mero de iteraes calculado usando-se a seguinte e u co e expresso: a f inal inicial + inc M AX ,0 (2.2) inc Quando o resultado acima 0 ou negativo, o loop no executado. A tabela abaixo e a e mostra alguns exemplos do comportamento do DO para diferentes argumentos. Note que mesmo no caso em que nada executado pelo loop (ltima linha da tabela, em que o e u nmero de iteraes 0) atribuido um valor do contador (i). u co e e DO DO DO DO DO DO Nmero de iteraes u co 10 7 7 1 0 Valores do contador 1,2,3,4,5,6,7,8,9,10 20,25,30,35,40,45,50 20,14,8,2,-4,-10,-16 4 6
Exemplo de uma funo inteira que calcula o fatorial de um nmero inteiro (arquivo ca u fatorial.f90): INTEGER FUNCTION fatorial ( arg ) IMPLICIT NONE INTEGER , INTENT ( in ) :: arg INTEGER :: i ! Contador do loop ! Caso em que arg eh 0 IF ( arg == 0) THEN fatorial = 1 ELSE fatorial = 1 DO i =1 , arg fatorial = fatorial * i ENDDO ENDIF END FUNCTION fatorial
2.11.2
Comando EXIT
O EXIT permite terminar o loop quando alguma condio for satisfeita. Esse tipo de ca construo muito util quando se usa mtodos iterativos para calcular algo com preciso ca e e a pr-determinada e DO . . IF ( precisao < epsilon ) EXIT . 27
END DO ! Ap s o EXIT o programa segue seu curso normal o O uso do cdigo acima perigoso pois pode-se incorrer num loop innito, caso a o e condio do IF nunca seja satisfeita. Para contornar este problema basta impor um ca nmero mximo de iteraes, como no exemplo abaixo: u a co DO i =1 , max_iteracoes . . IF ( precisao < epsilon ) EXIT . END DO
2.11.3
Exerc cio
Escrever um programa que calcule o valor de usando a srie da Eq. (2.1), com a preciso e a denida pelo usurio e que imprima o resultado e o nmero de termos que foram somandos. a u Como denir se a preciso foi atingida? a
2.12
Arrays
Em computao cient ca ca frequentemente necessrio manipular conjuntos de dados ore a denados, tais como vetores e matrizes. Outro tarefa comum repetir a mesma sequncia e e de operaes em um conjunto de dados. co Ambos requerimentos so atendidos em Fortran pelo uso de arrays, que permitem que a um conjunto de dados seja acessado simultneamente (como um unico objeto). a H duas formas de se declarar um array: a REAL , DIMENSION (50) :: a REAL :: a (50) Ambas as formas so equivalentes. Para imprimir os elementos 11 a 14 de a basta a escrever: PRINT * , a (11:14) Por padro o primeiro a ndice de um array 1, mas isso pode ser modicado, como no e exemplo abaixo: REAL , DIMENSION ( -10:1) :: a Em Fortran, pode ocorrer confuso entre arrays e funes pois a sintaxe semelhante. a co e Considere o exemplo abaixo:
28
REAL , DIMENSION (10) :: primeiro REAL :: segundo INTEGER :: i REAL :: a , b ... a = primeiro ( i ) b = segundo ( i ) ... Os dois comandos tm a mesma forma, mas no primeiro o (i) o e e ndice de um array, ento o compilador simplesmente atribui o i-simo valor de primeiro em a. J no segundo a e a comando, como no h o atributo de dimenso na varivel segundo, o compilador assumir a a a a a que se trata de uma funo real externa. ca
2.12.1
Inicializando um array
Arrays podem ser inicializados de vrias formas. Atribuio direta: a ca arr_inteiro = (/1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10/) Para arrays grandes, usa-se o DO impl cito: arr_inteiro = (/( i , i =1 ,10)/) Essa uma construo poderosa, que pode tomar vrias formas: e ca a arr_real = (/( SQRT ( REAL ( i )) , i =1 ,1000)/) arr_inteiro = (/((0 , i =1 ,9) ,10* j , j =1 ,10)/)
2.12.2
Quando aparecem em expresses sem referncias aos o e ndices, ento implicitamente est se a a referindo ao array todo: PRINT * , arr_inteiro Subarrays tambm podem ser facilmente extra e dos: PRINT * , ( p ( i ) , i =1 ,99 ,2) PRINT * , p (10:20) Exemplo de uma construo perigosa: ca READ * , primeiro , ultimo , ( arr ( i ) , i = primeiro , ultimo ) 29
Por qu perigosa? Se no tomar cuidado pode-se ter problemas de memria (segmentation ee a o fault, ou falha de segmentao). Por exemplo, se arr for um array de 1 a 10, e o valor de ca ultimo for 11, teremos problemas...
2.12.3
Denies: co 1. Dois arrays so conformes se eles tiverem a mesma forma (igual nmero de dia u menses e nmeros de elementos em cada dimenso). o u a 2. Um escalar sempre conforme com um array. e 3. Todas as operaes intr co nsecas so vlidas entre dois arrays conformes. a a Exemplos de expresses aritmticas envolvendo arrays: o e REAL :: a (20) , b (20) , c (20) , maximo , soma , media REAL :: x (3) , y (3) REAL :: pe , co a = b * c ! Esse comando equivalente ` : e a DO i =20 a ( i ) = b ( i )* c ( i ) END DO a = 10.* c c = 2. b = SIN ( c ) maximo = MAX ( a )
! Calcula a soma de todos os elementos do array soma = SUM ( a ) ! Calcula a m dia aritm tica dos elementos do array e e media = SUM ( a )/ SIZE ( a ) ! Calcula o produto escalar de dois vetores pe = SUM ( x * y ) ! Calcular o comprimento de um vetor : co = SQRT ( SUM ( x * y ))
2.12.4
Arrays em procedimentos
O Fortran permite que arrays em procedimentos tenham um nmero de elementos indeu nido. Esse nmero denido ao longo da execuo. Este recurso extremamente util, e u e ca e deve ser adotado sempre, como uma boa prtica de programao. a ca Exemplo:
30
SUBROUTINE exemplo ( array1 , array2 ) IMPLICIT NONE REAL , DIMENSION (:) :: array1 , array2 INTEGER :: N ... ! Tamanho do array N = SIZE ( array1 ) ... Se essa subrotina for chamada de um programa que tem as declaraes: co REAL , DIMENSION (20) :: a , b ... CALL exemplo (a , b ) ento internamente as variveis array1 e array2 tero dimenso 20. a a a a
2.13
Vimos antes o list-directed input e output. Apesar de prticos, os comandos READ* e a PRINT* no so sucientes na maioria das situaes, pois frequentemente necessrio a a co e a mais controle na forma da entrada e sa da. O fortran permite tal controle atrves de strings de formatao. Dessa forma, o a ca READ* e o PRINT* so substitu a dos por comandos mais gerais, como abaixo: READ (* , formato ) arg1 , arg2 , ... WRITE (* , formato ) arg1 , arg2 , ... sendo que formato se refere a uma string (ou uma varivel string) que contm o cdigo a e o de formatao. ca Para formatar n meros reais, usa-se os descritores F e E: u - NFw.d: escreve um nmero real nas prximas w letras com d casas decimais. Esse u o formato ser repetido N vezes. a - NEw.d: escreve um nmero real em formato exponencial nas prximas w letras com u o d casas decimais. Lembrar que 4 caracteres so usados pelo expoente. Esse formato a ser repetido N vezes. a Para formatar caracteres usa-se o descritor A: NAw. Exemplo abaixo ilustra como se deve usar estes formatadores (ver arquivo formatos.f90) WRITE (6 , " (5 A16 ) " ) " Argumento " , " Raiz Quadrada " , " Raiz & & Cubica " , " Raiz Quadrupla " , " Raiz Quintupla " WRITE (6 , " (5 F16 .4) " ) arg , raiz2 , raiz3 , raiz4 , raiz5 WRITE (6 , " (5 E16 .4) " ) arg , raiz2 , raiz3 , raiz4 , raiz5 31
A sa do cdigo acima : da o e >> Argumento Raiz Quadrada >> 10.0000 3.1623 >> 0.1000 E +02 0.3162 E +01 >> Raiz Quintupla >> 1.5849 >> 0.1585 E +01 Raiz Cubica 2.1544 0.2154 E +01 Raiz Quadrupla 1.7783 0.1778 E +01
Para formatar nmeros inteiros, usa-se o descritor I: u - NIw: escreve um nmero inteiro nas prximas w letras. Esse formato ser repetido N u o a vezes. Exemplo: WRITE (* , " (A , I1 ,A , F6 .4) " ) " x **1/ " ,2 , " = " , raiz2 Sa da: >>x **1/2 = 4.4721
2.14
Usando arquivos
Para poder ler e escrever dados de uma outra unidade lgica alm do teclado (tipicao e mente um arquivo, mas pode ser outro dispositivo), deve-se inicialmente conectar-se a essa unidade. Isso feito pelo comando OPEN. Ex: e OPEN ( FILE = " tabela . txt " , UNIT =7 , STATUS = " NEW " , ACTION = " WRITE " ) A UNIT representa uma unidade lgica, associada a um nmero inteiro. Usando-se difeo u rentes unidades, pode-se acessar vrios arquivos simultaneamente. a O STATUS util para se denir certas restries ao uso de um dado arquivo. Por e co exemplo, podemos querer garantir que no escreveremos nada por cima de um arquivo. a H trs opes principais a e co - OLD: nesse caso, o arquivo j deve existir previamente para poder ser aberto. a - NEW: nesse caso, o arquivo no deve existir previamente para poder ser criado. a - UNKNOWN: nesse caso, se o arquivo j existe, ele ser tratado como OLD, caso contrrio a a a como NEW. Podemos tambm especicar que tipo de aes de input/output so permitidas usando e co a o ACTION, que pode tomar trs valores: e - READ: nesse caso o arquivo tratado como sendo apenas para leitura. No poss e a e vel escrever nele. - WRITE: nesse caso o arquivo apenas para escrita. Comandos READ no so permie a a tidos 32
- READWRITE: tanto input quanto output so permitidos. a Arquivos so acessados usando-se os comandos READ e WRITE. Por exemplo, se houver a um arquivo associado ` unidade 7, podemos escrever neste arquivo usando o seguinte a comando: WRITE ( UNIT =7 , FMT = < formato >) ... ou simplesmente WRITE (7 , < formato >) ... Quando o acesso ao arquivo no mais necessrio, deve-se fechar a conexo: a e a a CLOSE ( UNIT =7) O exemplo arquivos.f90 usa o cdigo do programa formatos.f90 e escreve o resulo tado num arquivo cujo nome fornecido pelo usurio. e a
33