CPC782 Fundamentos de Programação Introdução ao Fortran Renato N. Elias / Marcos A. D. Martins Antes de começarmos... Devemos saber responder algumas questões BASTANTE básicas: – – – – – – – – – – O que é um programa de computador? Por que eu preciso aprender a programar? O que é um arquivo ou código fonte? O que é um objeto ou arquivo compilado? O que é uma linguagem de programação? O que é lógica de programação? O que é um pré-processador? O que é um compilador? O que é um linker? O que é uma biblioteca? Como aprender uma linguagem de programação? slide de (des)motivação para aprendizado de qualquer linguagem de programação 1. Precise dela!!!!! “Se eu não preciso, por que tenho de aprendê-la?” 2. Tenha prazer em programar como quem está para decifrar um enigma. “Como eu faço esse computador fazer o que eu quero?” 3. Pegue um programa simples, contendo bons comentários passo-a-passo e tente utilizar os fragmentos que se assemelham com o que se deseja fazer como um modelo. “Guarde esse programa-modelo em um cofre a sete chaves até se sentir seguro o suficiente para programar sozinho” 4. Comece a programar com a ajuda de um bom ambiente de programação. “mas nunca se torne escravo dele” 5. Não desanime, seja persistente! “Errar é a melhor parte do processo de aprendizado pois os erros, geralmente, são mais facilmente assimilados do que os acertos” 6. Não tenha medo de tentar! “O (bom) compilador adora nos humilhar mostrando nossos deslizes, além disso, um simples programa não irá fazer o computador explodir -- mas talvez ele precise ser reiniciado...” A good programmer is someone who looks both ways before crossing a one-way street. -- Doug Linder, systems administrator Desenvolvendo programas Planejar; – Lógica de programação Desenvolver; – Linguagem (C/C++, Fortran, Java, etc...) – Ambiente de programação (Vi, Notepad, Visual Studio, KDE developer, etc...) Pré-processar, compilar e “linkeditar” – Compiladores (Intel, G95, PGF90, Compaq, etc...) Testar (depuração); – Ambiente de programação Corrigir (depuração); – Ambiente de programação Commentary: most debugging problems are fixed easily; identifying the location of the problem is hard. -- unknown Construindo um programa Pré-processamento “linkedição” ou “linkagem” Compilação fonte pré-processado compilado arq1.f90 arq1.i arq1.obj fonte pré-processado compilado programa arq2.f90 arq2.i arq2.obj foo.exe fonte pré-processado compilado arq3.f90 arq3.i arq3.obj O que eu preciso para programar em Fortran? Um editor de textos, um compilador ou um ambiente de programação que forneça o editor de textos e o compilador juntos Em Windows: – Compaq Visual Studio (comercial) – Visual Studio + Intel Fortran (comercial) – Fortran Force (gratuito: http://www.guilherme.tk/) Em Unix e similares: – – – – G77 (gratuito – não recomendado); Sun Studio (gratuito); Intel Fortran (gratuito para uso não comercial) Compilador do Portland Group (comercial) Referências Google, Google, Google – 34.300.000 referências para a palavra Fortran Fortran Wikipedia: – http://pt.wikipedia.org/wiki/Fortran Fortran Standards Technical Commitee – http://www.j3-fortran.org/ Livros: – Stephen J. Chapman, “Fortran 90/95 for Scientists and Engineers” – James F. Kerrogan, “Migrating to Fortran 90” Apostila: – http://www.nacad.ufrj.br/~rnelias/fortran Fortran – Um pouco de história Criada em 1954-57 por uma equipe da IBM chefiada por John Backus; Nome da linguagem derivado de seu principal propósito FORmula TRANslator Primeira linguagem de programação de alto nível desenvolvida para computadores; Com sua rápida popularização surgiu a necessidade de uma padronização em 1966 (Fortran IV ou Fortran66) Sofreu algumas modificações em 1977 (Fortran77) Outras atualizações: – – – – Fortran90 (1993); Fortran95 (1997); Fortran2003; HPC (High Performance Fortran) Motivos para NÃO APRENDER Fortran Programação de interface gráfica (GUI); Programação de bancos de dados; Programação voltada para internet; Programação que utilize manipulação intensiva de strings; Programação dirigida a objetos (OOP). Motivos para APRENDER Fortran Fácil de aprender, desenvolver e depurar; Extremamente eficiente na execução de CÁLCULOS; Milhares de bibliotecas científicas testadas, otimizadas e distribuídas gratuitamente para uso com o Fortran; Deficiências anteriores ao Fortran 90 Exigência de uso de formato fixo para codificação; Impossibilidade de acesso dinâmico de dados; Inabilidade de representação implícita de operações em arrays Falta de portabilidade (padrão definido pelo fabricante) Impossibilidade de definição de tipos pelo programador; Inexistência de recursividade; Acesso aos dados globais através de COMMON blocks Recursos adicionados ao Fortran90 Formato livre de arquivos; Sintaxe própria para operações com arrays Alocação dinâmica e inclusão de pointers Tipos de dados portáveis (KIND) Tipos de dados derivados e operadores Recursividade Modules em substituição e extensão aos COMMON BLOCKS Estruturas de controle mais aprimoradas I/O aprimorado O que iremos aprender? Fortran IV Fortran 90 FORTRAN Fortran 77 Fortran 95 Fortran 2003 Elementos da linguagem O Fortran não é sensível à letras maiúsculas e minúsculas: Casa = casa = CASA = cASA = cAsA = CaSa Formatos de arquivos aceitos pelo Fortran – – Fixo (extensões *.for, *.f77, *.f, *.F) Livre (extensões *.f90, *.F90) Caracteres de comentário – – Linhas contendo os caracteres “c” ou “C” na coluna 1 Qualquer texto iniciado pelo caractere “!” Rótulos (labels) – Números de (1 a 99999) colocados nas 5 primeiras colunas Continuação de linha – – Formato fixo: linha que possui qualquer caractere na coluna 6 Formato livre: Qualquer linha finalizada com um ampersand (&) Vários comandos em uma mesma linha – Separar os comandos com um ponto e vírgula “;” Formatos de arquivos FIXO LIVRE Comentários e continuação de linha Formato fixo (arquivo hello.f) Formato livre (arquivo hello.f90) Outras perguntas básicas... O que é uma variável? a = 1.0 i = 1 str = ‘Fortran’ O que é um tipo? – O tipo de uma variável informa ao compilador, e consequentemente ao programa, como o computador deverá interpretar a variável. – No exemplo acima a, i e str ocupam quantidades distintas de memória devido aos seus TIPOS serem também diferentes. Evitando dores de cabeça Faça comentários significativos nos seus programas: – Comentário inútil i=0 ! i recebe valor 0 – Comentário útil i=0 ! i está sendo zerado pois será utilizado como ! contador do próximo loop Crie nomes de variáveis auto-explicativos – Variável pouco explicativa: integer :: n – Variável auto-explicativa: integer :: NumberOfNodes Endente seu programa para facilitar a leitura Tente usar somente funções intrínsecas da linguagem – Compatibilidade = portabilidade = flexibilidade – Se for usar bibliotecas, procure se informar se essa biblioteca estará disponível nos sistemas que pretende usar Estrutura básica de um programa Fortran program <nome_do_programa> ! declaracao de modules use dados ! declaracao de variaveis integer :: n, k, l ! corpo do programa n = 1 k = 2 l = n+k print *, l ! finalizacao do programa end program Tipos de dados Inteiro integer :: n = 1 Real de precisão simples real*4 :: a = 3.0 ! 7 casas de precisão real(4) :: a = 3.0E1 real :: a = 3. Real de precisão dupla double precision :: a = 2.5d0 ! 15 casas de precisão real*8 :: a = 2.5D0 real(8) :: a = 2.5D0 Lógico logical :: ok = .false. Tipos de dados (continuação) Complexo de precisão simples complex*8 :: c = (1.,4.) complex :: c = (1.3,4.1E1) Complexo de precisão dupla complex*16 :: c = (1.d0,4.d0) Character character :: str*80 character(80) :: str character*80 :: str character*80 str Tipos de dados derivados Permite a criação de tipos de acordo com a necessidade do programador Type employee_name SEQUENCE ! (Opcional) preserva a ordem de armazenamento dos campos character(25) last_name character(15) first_name END TYPE employee_name Type employee_data TYPE (employee_name) :: name ! Usando o tipo previamente criado integer telefone integer age logical married END TYPE Usando um tipo derivado Type(employee_data) :: employee employee%name%last_name employee%name%first_name employee%telefone employee%age employee%married = = = = = 'Elias' 'Renato' 25628080 30 .true. ! Ver programa exemplo typeder.f90 Declaração implícita Antagonicamente NÃO recomendado, porém, bastante útil Declaração de tipo implicitamente determinada pela primeira letra do nome da variável: i,j,k,l,m,n: variáveis inteiras a-h, o-z: variáveis reais de precisão simples Modificando a declaração implícita implicit real*8 (a-h,o-z) implicit integer (i-k) Obrigando que todas as variáveis sejam explicitamente declaradas implicit none Na prática... program foo implicit real*8 (a-h,o-z) a = 2.d0 b = 3.d0 c = a+b print *, c end program program foo implicit none real*8 :: a,b,c a = 2.d0; b = 3.d0; c = a+b print *, c end program program foo implicit none a = 2.d0 b = 3.d0 c = a+b print *, c end program ERRADO!!!! produzirá erro de compilação Operadores Operadores Aritméticos símbolo + / * ** = // operação exemplo a + b x - y alfa/beta beta*gamma a**b -delta a = 1.0 ‘abc’//’def’ soma subtração divisão multiplicação potenciação menos unário atribuição Contatenação de strings Operadores Relacionais símbolo (F77) .EQ. .NE. .GT. .GE. .LT. .LE. símbolo (F90) == /= > >= < <= descrição Igual Diferente Maior Maior ou igual Menor Menor ou igual Operadores Lógicos Operador Exemplo Descrição .AND. A.and.B verdadeiro se A E B são verdadeiros .OR. A.or.B verdadeiro se ou A ou B forem verdadeiros .NOT. .not.A falso se A for verdadeiro e verdadeiro se A for falso .EQV. A.eqv.B verdadeiro se A e B forem ambos verdadeiros ou falsos A.neqv.B verdadeiro se A ou B for verdadeiro e falso se ambos forem verdadeiros .NEQV. Exemplo: considere aa=.true. = .true.ee bb=.false. = .false.para paraavaliar avaliaras asseguintes seguintesoperações operaçõeslógicas lógicas c = a .and. b ! c = .false. c = a .or. b ! c = .true. c = .not. a ! c = .false. c = a .eqv. b ! c = .false. c = a .neqv. b ! c = .true. Hierarquia entre operações 1. Parênteses mais internos 2. Cálculo de funções 3. Potenciação 4. Menos unário 5. Multiplicação e divisão 6. Adição e subtração 7. Concatenação Exemplo: x+1/x-1 é diferente de (x+1)/(x-1) Algumas funções intrínsecas Função Exemplo Descrição abs(x) |x| Valor absoluto de x. log(x) ln x Logaritmo natural de x log10(x) log x Logaritmo de x na base 10 sin(x) sen x Seno de X em radianos cos(x) cos x Cosseno de X em radianos acos(x) acos x Arco cosseno de x exp(x) ex Exponencial de x mod(i1,i2) Resto da divisão de i1 por i2 Observação: – algumas funções intrínsecas possuem versões específicas de acordo com o tipo de dado utilizado, por exemplo: dabs(x) ! x e o resultado da operação são real*8 iabs(n) ! n e o resultado da operação são integer Programa PI Programa PI: – Obter o valor de PI usando a função intrínseca ACOS do Fortran para obter o Arco-cosseno de -1 program PIValue real*4 :: pi_sp real*8 :: pi_dp pi_sp = acos(-1.) print *, ‘Pi in single precision is:’, pi_sp pi_dp = dacos(-1.d0) print *, ‘Pi in double precision is:’, pi_dp end program Inside every well-written large program is a well-written small program. -- Charles Antony Richard Hoare, computer scientist Aritmética inteira, real e mista Inteira 3/5 = 0 13/4 = 3 Real 3.0/5.0 = 0.6 3./5. = 0.6 13./4.0 = 3.25 Conversão automática de tipo: program conv integer :: nres nres = 1.25+9/4 print *, nres ! imprimirá 3 ao invés de 3.5 end program ATENÇÃO: Mista 3.0/5 = 0.6 13/4.0 = 3.25 – Notem que embora o resultado da operação seja real, ele foi armazenado em uma variável do tipo inteiro ocasionando uma conversão automática. (EVITEM FAZER ISSO!!!) Evitando o uso de potenciação A potenciação é internamente implementada como uma operação com logarítmos, portanto, uma operação lenta e sujeita a erros result = y**2.0 ! internamente seria result = exp(x*ln(2.0)) Podemos evitar isso utilizando expoentes inteiros sempre que possível ou realizando a operação explicitamente: result = y**2 result = y*y Operações com strings Para o Fortran uma string é um array de characters program string character(3) :: str1, str2 character(6) :: str3 str1 = ‘ABC’ str2 = ‘DEF’ str3 = str1//str2 ! concatenando str1 com str2 print *, str3 print *, ‘ primeiras 2 letras de str1: ’, str1(:2) print *. ‘ ultimas 4 letras de str3: ‘, str3(3:6) end program Let’s do something... Programa DegToRad para converter graus em radianos – se 180º equivale a pi radianos, então, usando a nossa velha conhecida regra de 3: xo = x*pi/180 program DegToRad real*8 :: ang, PI PI = dacos(-1.d0) ang = 45 print *, ang ,‘ graus = ’, ang*PI/180.0, ‘ radianos’ end program Comandos condicionais Os comandos condicionais causam desvios no fluxo natural do programa de acordo com a avaliação de alguma expressão lógica Em Fortran, os comandos condicionais básicos são: – IF (lógico) – IF, THEN, ELSEIF, ENDIF – CASE Comandos condicionais IF (lógico): – executa, ou não, uma operação de acordo com a avaliação de uma expressão lógica (Booleana) if (a<10.0) a = 0.0 IF, THEN, ELSE, ELSEIF: – desvia a execução do programa de acordo com a avaliação de uma, ou várias, expressão(ões) lógica(s) nome: if (teste logico) then ! corpo do if end if nome ! os nomes são opcionais e geralmente utilizados para ! fins de identificacao IF, THEN, ELSE, ELSEIF (continuação...) ! Exemplo 1 if (b > c) then a = a+1 c = 0 else a = a–1 b = 10 endif ! Exemplo 2 idade: if (age>18) then print *, ‘maior’ else print *, ‘menor’ endif idade ! Exemplo 3 if (b > c) then a = a+1 c = 0 elseif (c.eq.a) then a = a-1 b = 10 else a = a+2 b = 0 endif Repare que o elseif nada mais é do que um if aninhado numa cláusula else Comandos condicionais SELECT CASE: – Este comando pode substituir uma série de if’s aninhados, porém, ele só pode ser utilizado com variáveis INTEGER e CHARACTER nome: select case (i) case(:-1) ! todos os valores inteiros menores que 1 print *, ‘numero negativo’ case(0) ! somente se i for igual a 0 print *, ‘ zero ‘ case(1:9) ! numeros inteiros entre 1 e 9 print *, ‘ numero de 1 unico digito: ‘ case(10:99) ! numeros inteiros entre 10 e 99 print *, ‘ numero de 2 digitos ‘ end select nome Comandos de repetição Os comandos de repetição, laços ou loops são utilizados na execução de um ou mais comandos repetidas vezes. Em Fortran, os comandos de repetição são: – DO (simples e infinito) – WHILE – Loops implícitos (veremos mais tarde quando tratarmos de variáveis indexadas) Existem comandos auxiliares que controlam a saída forçada de dentro de um laço, são eles: exit cycle [label]: goto [label]: return: Comandos de repetição DO: – Os laços DO em Fortran são a forma mais natural de se realizar uma ou mais operações repetidas vezes. Nesse tipo de laço uma variável de controle é utilizada como contador e, consequentemente, como critério de parada para o laço. Forma geral: nome: DO <variável de controle> = inicio, fim, incr ! corpo do laço ENDDO nome Observações: – Se o incremento for unitário o mesmo poderá ser omitido – O incremento poderá ser negativo (decremento) – A variável de controle não deve ser alterada no interior do laço DO: O que podemos fazer... ! Exemplo 1: DO i=1,10 print *, i ENDDO ! Exemplo 2: DO n=1,10,3 print *, n ENDDO ! Exemplo 3: DO j=10,1,-1 print *, j END DO ! Exemplo 4: i0=-5; i1=30; inc=4 DO n=i0,i1,inc print *, n ENDDO ! Exemplo 5: h=0.5 DO x=4.0,7.9,h print *, x ENDDO ! Exemplo 6: externo: DO i=5,10 interno: DO j=10,1,-1 print *, ‘i+j vale:’, i+j ENDDO interno ENDDO externo DO: O que NÃO podemos fazer... ! Exemplo 1: DO i=1,10 i = i+1 ! i não deve ser usado em ! calculos dentro do loop ENDDO ! Exemplo 2: DO i=1,10 DO i=10,1 ! 2 loops com a mesma ! variável de controle ENDDO ENDDO ! Exemplo 3: DO i=1,10 j = j+1 DO j=10,1 ! variavel de controle ! do segundo loop sendo ! usada no primeiro loop ENDDO ENDDO ! Exemplo 4 externo: DO i=1,10 interno: DO j=1,10 ! laços cruzados enddo externo enddo interno Comandos de repetição DO WHILE: – O laço DO WHILE executa uma ou mais operações “ENQUANTO” uma condição esteja sendo satisfeita (avaliada como verdadeira). Forma geral: nome: DO WHILE <teste lógico> ! corpo do laço END DO nome Observações: – Ao contrário do que ocorre com o laço DO, no DO WHILE a variável de controle utilizada no teste lógico, pode (e geralmente é) utilizada em alguma operação no corpo do laço DO WHILE em exemplos: ! Exemplo 1 i=0 DO WHILE (i<=10) print *, i i = i + 1 END DO ! Exemplo 2 logical :: Ok = .false. i=1; j=50 DO WHILE (.not.Ok) i=i+1 j=j-2 Ok = i>j print *, Ok, i, j ENDDO Comandos de repetição DO infinito: – O Fortran 90 introduziu o conceito de DO infinito, ou eterno. Nesse tipo de laço uma ou mais operações são repetidas indefinidamente (o que faz pouco sentido em programação) ou até que algum comando force a saída de dentro do laço Forma geral: DO ! corpo do loop if <satisfeita uma condição> exit ENDDO DO infinito em 1 exemplo program CelsiusToKelvin real*4 :: celsius character :: opt*1 DO print *, 'Entre com a temperatura em Celsius:' read(*,*) celsius ! falaremos do comando READ mais tarde print *, celsius, ' Celsius = ', celsius+273.15, ' Kelvin' print *, 'Deseja sair (S/N)' read(*,*) opt if (opt.eq.'s'.or.opt.eq.'S') exit ENDDO end program Complicando o que deveria ser simples... program DOCycle cycle_loop: do i = 1, 5 print *,i if (i.gt.3) cycle cycle_loop print *,i end do cycle_loop print *,'done!' end program ! Quando i torna-se maior que 3 o loop só é ! executado até o cycle