Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Linguagem Fortran, Notas de estudo de Engenharia de Alimentos

introdução do programa

Tipologia: Notas de estudo

Antes de 2010

Compartilhado em 15/07/2009

thiago-colombo-6
thiago-colombo-6 🇧🇷

5

(1)

1 documento

1 / 14

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Introdução à Programação na linguagem F
Jaime Ramos, Amílcar Sernadas e Paulo Mateus
DMIST, Outubro de 2003
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe

Pré-visualização parcial do texto

Baixe Linguagem Fortran e outras Notas de estudo em PDF para Engenharia de Alimentos, somente na Docsity!

Introdução à Programação na linguagem F

Jaime Ramos, Amílcar Sernadas e Paulo Mateus

DMIST, Outubro de 2003

Capítulo 1 Introdução à linguagem F

Objectivos

Introdução à linguagem F. Edição e compilação de programas. Tipos primitivos e expressões. Declaração de variáveis. Atribuição. Composição sequêncial, iterativa e alternativa de comandos. Definição de funções e subrotinas. Efeitos colaterais. Programação recursiva.

Conceitos básicos

A linguagem F é um fragmento cuidadosamente escolhido da linguagem de programação Fortran 95. Considere-se o seguinte programa F, para somar os números inteiros entre 1 e 50.

program exemplo

integer :: i, r

r= do i=1, r=r+i end do print *,"Resultado:",r end program exemplo

Antes de proceder à análise do programa, covém perceber como é que se edita, compila e executa um programa em F. A edição do programa é feita do modo usual: recorrendo a um editor de texto (por exemplo o Notepad), escreve-se o código do programa num ficheiro com extensão f95. Neste caso, deu- se ao ficheiro o nome exemplo1.f95 (embora não seja obrigatório, é usual e conveniente dar ao ficheiro o mesmo nome do programa).

Em seguida, é necessário compilar o programa. Para tal, é necessário ter instalado no computador em que se está a trabalhar um compilador para a linguagem F (que pode ser obtido em www.fortran.com/F). A compilação do ficheiro é feita através do editor de comandos do Windows ( command prompt ). Antes de compilar é necessário indicar ao computador onde se encontra o ficheiro que se pretende compilar. O processo mais fácil consiste em ir para esse local. No caso do exemplo, o ficheiro exemplo1.f95 encontra-se na pasta C:\Fortran\CP\examples\cap01. Para chegar até é necessário executar comando cd ( change directory ) no editor de comandos:

cd Fortran\CP\examples\cap

Podemos finalmente compilar o programa:

f exemplo1.f

No caso da compilação ser bem sucessida (não ocorerem erros), o resultado é um ficheiro executável (extensão exe) que pode ser executado, também através do editor de comandos. Neste caso, a compilação anterior gerou um ficheiro a.exe, que pode ser executado da seguinte forma:

a.exe Resultado: 1275

que apresenta no ecrã o resultado da execução do programa exemplo1, que neste caso consiste na soma dos 50 primeiros números naturais. Alternativamente, podemos compilar o programa para um ficheiro executável com um nome mais apelativo. Para tal, utiliza-se uma opção disponível no compilador que permite fixar o nome do ficheiro executável resultante da compilação, a opção –o. Por exemplo, podemos compilar o programa anterior para o ficheiro exemplo1.exe através do comando:

Existem também em F instruções de leitura. O programa seguinte, guardado no ficheiro exemplo2.f95, utiliza a instrução read para ler do terminal dois números inteiros para as variáveis x e y. Em seguida soma os números inteiros entre x e y:

program exemplo

integer :: x, y, i, r

print *,"Valor inicial:" read *,x print *,"Valor final:" read *,y r= do i=x,y r=r+i end do print *,"Resultado:",r end program exemplo

Então, após compilar o programa:

f exemplo2.f95 –o exemplo2.exe

podemos executá-lo. O resultado é o seguinte:

exemplo2.exe Valor inicial: 1 Valor final 50 Resultado: 1275

Os valores 1 e 50 foram introduzidos pelo utilizador, a partir do terminal, e lidos para as variáveis x e y, respectivamente, através da instrução read.

Tipos primitivos e expressões

Existem 5 tipos de dados primitivos disponíveis em F: integer, real, complex, logical e character. Mais tarde, serão apresentadas construções que permitem definr tipos mais complexos em F.

Tipo integer: os objectos deste tipo correspondem aos números naturais. Por exemplo, 45 , 0 , - são objectos de tipo integer. Há ainda a possibilidade de escolher a representação destes números (long ou short) essa discussão é adiada para um capítulo subsequente.

Tipo real: os objectos deste tipo correspondem aos números reais. Por exemplo, 3.1416, 0.13, 3. são objectos de tipo real. Tal como no tipo integer, é possível escolher a representação destes números.

Tipo complex: os objectos deste tipo correspondem aos números complexos, com a representação a+bi , em que tanto a como b são números reais. Por exemplo, (1.5, 1.3) é um objecto de tipo complex que corresponde ao número complexo 1.5 + 1.3i.

Tipo logical: os objectos deste tipo correspondem aos valores de verdade. As constantes são .true. e .false. correspondendo a verdadeiro e a falso, respectivamente.

Tipo character: os objectos deste tipo correspondem a cadeias de caracteres (delimitadas por aspas). Por exemplo, "Joao" e "ola" são objectos de de tipo character.

Estão disponíveis operações aritméticas definidas sobre cada os tipos números, como por exemplo, operações usuais + (adição), - (subtracção), * (multiplicação), / (divisão). Estas operações, quando aplicadas a dois objectos do mesmo tipo resultam num objecto desse tipo, ou seja, adicionar dois números inteiros resulta num número inteiro, multiplicar dois números reais resulta num número real, etc. Nomeadamente, a divisão de dois números inteiros resulta num número inteiro. Por exemplo, o resultado de avaliar a expressão 15/2 em F é o número inteiro 7. Obviamente, estas operações numéricas podem ser aplicadas a objectos de diferentes tipos. Nesse caso, prevalece o tipo mais geral. Por exemplo, somar um número inteiro com um número real resulta num número real, enquanto multiplicar um número real por um número complexo resulta num número complexo. Para além destas, existem outras operações aritméticas definidas em F, cujas listagem exaustiva se omite. Deixa-se como exercício, interpretar expressão n-(n/i)*i em que n e i são variáveis de tipo integer.

Para além das operações aritméticas, estão disponíveis também as habituais operações relacionais. Os mais frequentes são: == (igualdade), /= (diferente), < (menor), <= (menor ou igual), > (maior), >= (maior ou igual). O resultado de uma operação relacional é um objecto de tipo logical. Por exemplo, a expressão 2>=0 será avaliada em F para o valor .true., enquanto a expressão 0>3 será avaliada para .false.. É preciso cuidado na comparação de números reais e complexos usando as operações == e / =, devido a eventuais erros de aproximação.

Relativamente aos objectos de tipo logical, estão disponíveis as seguintes operações: .not., .and., .or., .eqv., and .neqv.. Estas operações podem ser aplicadas a objectos de tipo logical sendo o resultado também um objecto de tipo logical. P exemplo, a expressão 2>0 .and. 3>2 quando avaliada em F resulta no valor .true..

Composição alternativa de instruções

Em F, a composição alternativa de instruções tem duas formas principais. A primeira, manda executar uma instrução caso a condição seja verdadeira e não faz nada se esta for falsa:

if (condição) then instrução end if

A segunda forma permite mandar executar uma instrução no caso da condição ser falsa:

if (condição) then instrução else instrução end if

A condição tem que estar entre parenteses.

O exemplo seguinte, guardado no ficheiro exemplo3.f95, ilustra-se a utilização destas duas formas:

program exemplo

integer :: n, i, d

print *,"Introduza um numero:" read ,n d= do i=2,n- if (n-(n/i)i == 0) then d=d+ end if end do if (n>1 .and. d == 0) then print *,"O numero e primo." else print *,"O numero nao e primo."

O incremento também pode ser negativo, mas neste caso há que garantir que o valor inicial é maior do que o valor final. Considere-se o programa seguinte, para calcular o factorial de um número.

program exemplo

integer :: n, r, i

print *,"Introduza um número: " read ,n r= do i=n,1,- r=ri end do print *,"O factorial e: ",r end program exemplo

Neste caso, a variável i toma o valor inicial n e é decrementada até se atingir o valor 1.

Existem ainda outras formas de controlar a execução de uma instrução iterativa e que serão ilustradas mais à frente.

Funções e subrotinas auxiliares

Ao desenvolver um programa, é muitas vezes necessário definir funções e subrotinas auxiliares. No seguimento, apresentam-se alguns exemplos onde a definição de funções e subrotinas auxiliares se releva útil. Mais à frente, estes conceitos voltam a ser aplicados ao desenvolvimento de grandes programas, segundo a metodologia da programação modular por camadas baseadas em objectos.

Suponha-se que se pretende desenvolver um programa para contar o número de números primos que existem até um determinado número n, dado pelo utilizador. Embora seja possível desenvolver um programa em F, sem recorrer a procedimentos auxiliares, tal solução tem diversos inconvenientes, entre os quais se destacam: o desenvolvimento do programa é mais complexo, a detecção de erros é mais difícil e a leitura do programa mais complicada. Uma solução consiste em definir uma função auxiliar que testa se um número é primo e utilizar essa função para construir o programa principal.

Uma função em F pode ser utilizada como qualquer função primitiva. Não pode ter efeitos colaterais e devolve sempre um valor. Uma subrotina assemelha-se a uma função, mas não devolve valor, embora alguns dos seus parâmentros possam ser utilizados para devolver valores ao programa que a invocou, e pode também ter efeitos colaterais.

Suponha-se então que se dispõe de uma função prime para testar se um determinado número é primo. Uma solução para o problema apresentado é o programa seguinte:

program exemplo

integer :: n, i, r

print *,"Introduza um numero:" read *,n r= do i=1,n if (prime(i)) then r=r+ end if end do print *,"Existem",r,"primos ate",n end program exemplo

Se tentarmos compilar o programa anterior obtemos um erro de compilação pois a função prime não é conhecida. É necessário definir esta função e torná-la conhecida para o programa.

Comecemos pela definição da função. A estrutura de uma função em F é semelhante à de um programa:

function prime(n) result(b) integer, intent(in) :: n logical :: b integer :: i, d

if (n<=1) then b= .false. else d= do i=2,n- if (n-(n/i)*i == 0) then d=d+ end if end do if (d==0) then b=.true. else b=.false. end if end if end function prime

As principais diferenças de uma função para um programa são a utilização da instrução function em vez da instrução program, e a necessidade de declarar os parâmetros e o resultado da função. Neste caso, a função prime tem um parâmetro de entrada n de tipo inteiro e um resultado b de tipo logical. A declaração intent(in) serve para indicar que o parâmetro apenas pode ser utilizado para passar valores à função. Veremos a seguir que podem exister outros tipos de argumentos quando se definirem subrotinas. Em tudo o resto a definição da função é semelhante a um programa.

Falta apenas disponibilizar esta função ao programa anterior. A solução mais simples consiste em declarar esta função no fim do programa, após o corpo do programa e antes da instrução end program, usando a instrução contains. O ficheiro exemplo6.f95 contem a versão completa do programa:

program exemplo

integer :: n, i, r

print *,"Introduza um numero:" read *,n r= do i=1,n if (prime(i)) then r=r+ end if end do print *,"Existem",r,"primos ate",n

contains

function prime(n) result(b) integer, intent(in) :: n logical :: b integer :: i, d

if (n<=1) then b= .false. else d= do i=2,n- if (n-(n/i)*i == 0) then

print *,"Introduza um numero:" read *,n r= do i=1,n call prime(i,b) if (b) then r=r+ end if end do print *,"Existem",r,"primos ate",n

contains

subroutine prime(n,r) integer, intent(in) :: n logical, intent(out) :: r integer :: i, d

if (n<=1) then r= .false. else d= do i=2,n- if (n-(n/i)*i == 0) then d=d+ end if end do if (d==0) then r=.true. else r=.false. end if end if end subroutine prime end program exemplo

Ao chamar a subrotina prime, o resultado da chamada fica na variável b do programa, e é esta variável b que é usada para verificar se a variável r tem ou não que ser incrementada.

Do que foi visto, podemos concluir que uma função pode ser vista como um valor, isto é, pode ser utilizada numa expressão, enquanto uma subrotina pode ser encarada como uma nova instrução, que, ao ser executada, pode provocar uma mudança no estado do sistema. No caso exemplo anterior, cada chamada à subrotina prime provoca (eventualmente) uma alteração da variável b.

Apresentam-se em seguida alguns exemplos complementares de definição de funções e subrotinas auxiliares.

Recorde-se problema de calcular o factorial de um número. A primeira solução passa uma definir uma função auxiliar fact com um parâmetro e que devolve o factorial desse parâmetro

program exemplo

integer :: n

print *,"Introduza um numero:" read *,n print *,"Factorial:", fact(n)

contains

function fact(n) result(y) integer, intent(in) :: n integer :: y, i

y= do i=2,n y=y*i end do

end function fact end program exemplo

Eis alguns exemplos de execução:

exemplo8.exe Introduza um numero: 3 Factorial: 6

exemplo8.exe Introduza um numero: 5 Factorial: 120

Este problema poderia também ter sido resolvido através da definição de uma subrotina. Neste caso, temos duas hipóteses, utilizar um parâmetro como entrada e outro parâmetro como saída, ou utilizar apenas um parâmetro para entrada e saída dos dados. A primeira solução não apresenta nada de novo e deixa-se como exercício. A segunda tem a novidade de podermos ter parâmetros de entrada e saída simultânea.

program exemplo

integer :: n

print *,"Introduza um numero:" read *,n call fact(n) print *,"Factorial:", n

contains

subroutine fact(n) integer, intent(inout) :: n integer :: y, i

y=n do i=2,y- n=n*i end do end subroutine fact end program exemplo

Observe-se que na definição da subrotina foi utilizada a declaração intent(inout) para o parâmetro n. Isto significa que não só podemos passar valores à subrotina através do parâmetro, como este poderá ser alterado durante a execução da subrotina e essas aletrações reflectir-se-ão para fora. Com efeito, a chamada a esta subrotina a partir do programa principal reflecte isso mesmo. Antes da chamada, n guarda o número de que pretendemos calcular o factorial. Após a chamada da subrotina, n guarda o valor do factorial.

exemplo9.exe

Consiste em definir recursivamente funções à custa de outras funções. A definição de uma função ou subrotina recursiva em F é semelhante à definição de uma função ou subrotina. O facto de que a função ou subrotina ser recusriva tem que ser indicado explicitamente através da instrução recursive.

Recorde-se a expressão recursiva para definir o factorial de um número natural:

n! =

A função F seguinte calcula recursivamente o factorial de um número natural:

recursive function factR(n) result(r) integer, intent(in) :: n integer :: r

if (n==0) then r = 1 else r = n*factR(n-1) endif end function factR

O programa seguinte utiliza esta função para calcular o factorial de um número fornecido pelo utilizador:

program factorialR

integer :: n

print *,"Introduza um numero:" read *,n print *,"Factorial:",factR(n)

contains

recursive function factR(n) result(r) integer, intent(in) :: n integer :: r

if (n==0) then r = 1 else r = n*factR(n-1) endif end function factR end program factorialR

Considerem-se alguns exemplos de utilização:

factorialR.exe Introduza um numero: 4 Factorial: 24

factorialR.exe Introduza um numero: 1 Factorial: 1

Deixa-se como exercício, proteger a função contra argumentos indesejados. nomeadamente, contra números negativos.

Considere-se a sucessão Fn, n≥0, dos números de Fibonacci definida por

Fn =

A correspondente definição em F é a seguinte:

recursive function fibR(n) result(r) integer, intent(in) :: n integer :: r

if (n==0) then r = 0 else if (n==1) then r = 1 else r = fibR(n-2)+fibR(n-1) endif end function fibR

Podemos testar esta função através do programa:

program fib

integer :: n

print *,"Introduza um numero:" read *,n print *,"Numero de Fibonacci:",fibR(n)

contains

recursive function fibR(n) result(r) integer, intent(in) :: n integer :: r

if (n==0) then r = 0 else if (n==1) then r = 1 else r = fibR(n-2)+fibR(n-1) endif end function fibR end program fib

Apresentam-se em seguida alguns exemplos de utilização:

fib.exe Introduza um número: 2 Numero de Fibonacci: 1

fib.exe Introduza um número: 6 Numero de Fibonacci: 8