1 funções, expressões e excepções trajectórias Óptimas di/fct/unl 1º semestre 2004/2005
Post on 17-Apr-2015
127 Views
Preview:
TRANSCRIPT
1
Funções, Expressões e ExcepçõesTrajectórias Óptimas
DI/FCT/UNL
1º Semestre 2004/2005
2
Funções e Passagem de Parâmetros• Em muitos casos, ao invocar-se uma função pretende-se
obter não apenas um mas vários resultados.
• Este requisito é tratado diferentemente em diferentes linguagens de programação, dependendo em grande parte da forma como são passados os parâmetros de uma função.
• Em OCTAVE, os parâmetros são passados exclusivamente por valor (com uma excepção - nomes de funções).
• Isto quer dizer, que ao especificar-se uma variável no parâmetro de uma função a invocar, o que se passa para a função é o valor da variável.
• Durante a função, a variável não pode ser alterada no programa que invoca a função!
3
Passagem de Parâmetros por Valor• Exemplo: Consideremos a função
function y = f(x) x = 2*x y = xendfunction;
• Se chamada com o valor x = 5, durante a computação da função, esse valor é duplicado e retornado.
• Por exemplo, se invocarmos a função na sequência (pode ser ao terminal)
..., x = 5; z = f(x); x, z, ...
os valores de x e y reportados no terminal são x = 5 e z = 10.
4
Passagem de Parâmetros por Valor• Exemplo: ..., x = 5; z = f(x); x, z, ...
function y = f(x) x = 2*x; y = x;endfunction;
A computação da função f pode ser assim explicada: 1. Na instrução x=2*x o que é multiplicado por 2 é o valor
passado como parâmetro (i.e. 5) obtendo-se assim o valor 10.2. Esse valor é atribuído a uma nova variável, também chamada
x, mas que é local à função, não sendo alterado o x do programa principal.
3. Na instrução y=2*x, é a nova variável local que é considerada, e portanto, y = 10, valor esse retornado.
4. No “programa principal” esse valor é atribuído à variável z.
5
Passagem de Parâmetros por Referência• Outras linguagens (Pascal, C, C++, ...) permitem a passagem
de parâmetros por referência. Neste caso é passada a referência à variável do programa principal, que pode assim ser alterada pela função.
• Por exemplo se o parâmetro x fosse passado por referência (indicado com uma notação fictícia)
..., x = 5; z = f(x); x, z, ...
function y = f(ref w) w = 2*w; y = w;endfunction;
os valores de x e y reportados no terminal seriam x = 10 (a variável w, no interior da função é a mesma variável que a variável x, passada por referência!) e y = 10.
6
Funções com Múltiplos Resultados• A passagem de parâmetros por referência permite que uma
função (ou procedimento) passe vários valores para o programa que a invocou. Basta passar por referência as variáveis onde esses valores devem ser “colocados”.
• O OCTAVE, não suporta passagem de parâmetros por referência. A computação de vários resultados numa função é conseguida pela computação de um vector de resultados.
• Por exemplo, se se pretender que a função f, com argumento x, retorne dois valores, f1 e f2, especifica-se a função como
function [f1,f2] = f(x) ... f1 = ...; f2 = ...; ...endfunction;
7
Trajectórias Óptimas• Exemplo: Trajectórias
• A anterior função alcance(v,alfa,ka) determinava o alcance de um projéctil lançado com uma velocidade v e ângulo alfa, num meio em que o coeficiente de atrito é ka.
• Com essa função pode-se determinar (através de um ciclo) qual o maior alcance, mas não outras características da trajectória em que possamos estar interessados (por exemplo, altura atingida, tempo em que a atinge, tempo total da trajectória ou uma combinação destas características).
• Essas características, especificamente a altura atingida e o tempo total da trajectória podem ser retornados por uma função, tiro(v,alfa,ka), especificada de uma forma muito semelhante (a encarnado as diferenças).
8
Trajectórias Óptimasfunction [xmax, ymax, tmax] = tiro(vi, alfa, ka) dt = 0.01; g = 9.8; t = 0; ymax = 0; x = 0; vx = vi*cos(alfa*pi/180) ; y = 0; vy = vi*sin(alfa*pi/180); ax = - ka * vx ; ay = -g - ka * vy; while y >= 0 t = t + dt; x = x + vx * dt; y = y + vy * dt; if y > ymax
ymax = y; endif;
vx = vx + ax * dt; vy = vy + ay * dt; ax = - ka * vx; ay = -g - ka * vy; endwhile; xmax = x; tmax = t;endfunction;
9
Programas e Funções• Podemos agora responder a um conjunto de perguntas,
assumindo-se uma dada velocidade inicial e coeficiente de atrito, tais como:
– Qual a trajectória que atinge maior altura, com alcance mínimo de x_min? Qual a altura e qual o ângulo de disparo?
– Qual o alcance máximo atingido com uma trajectória que não dura mais de um tempo limite, t_limite? Qual o seu ângulo de disparo?
– Qual é a trajectória “máxima”, isto é cujo produto da altura máxima pelo alcance e pelo tempo é máximo? Qual o seu ângulo de disparo?
• Vejamos como responder à última destas questões.
10
Trajectórias Óptimasfunction [xmax, ymax, tmax, amax] = tiro_maximo(vi, ka)
maximo = 0;
for alfa = 0:90
[x, y, t] = tiro(vi,alfa,ka);
v = x*y*t
if v > maximo
maximo = v;
xmax = x; ymax = y;
tmax = t; amax = alfa;
endif;
endfor;
endfunction;
11
Programas e Funções
• Em muitas situações não se pretende o melhor mas apenas algo razoável. Consideremos por exemplo a questão:
– Será que existe uma trajectória (isto é, um lançamento feito a uma velocidade vi e um ângulo alfa, num meio com coeficiente de atrito ka) em que a altura seja maior que y1 e o alcance maior que x1?
• Esquemáticamente, devemos fazer uma pesquisa para todos os valores de vi, alfa e ka (com uma determinada precisão), o que se pode fazer encadeando 3 ciclos para (for).
• Assumamos que existem valores mínimos e máximos a respeitar para vi, alfa e ka e que a precisão a utilizar é, respectivamente, de 1ms-1, 1º e 0.1 s-1.
12
Trajectórias Óptimasfunction [v,a,k]=
bom_tiro(xmin,ymin,vmin,vmax,amin,amax,kmin,kmax) for vi = vmin:vmax for alfa = amin:amax for ka = kmin:0.1:kmax
[x, y, t] = tiro(vi,alfa,ka);
if x > xmin & y > ymin
v = vi; a = alfa; k = ka;
endif;
endfor;
endfor;
endfor;
endfunction;
13
Expressões Booleanas
• Este enunciado, embora correcto, é algo ineficiente, já que após a descoberta de uma boa trajectória, todas as restantes trajectórias são ainda calculadas!
• Esta ineficiência pode ser corrigida se se alterarem os ciclos “para” por ciclos “enquanto”, mas impondo na condição de entrada que não tenha sido ainda descoberta uma solução.
• Essa condição pode ser especificada através de uma expressão booleana, resultante da conjunção de duas expressões booleanas mais simples:
– A limitação normal do número de ciclos (p.ex. ka < kmax).
– Uma variável booleana, encontrada, que é falsa enquanto não tiver sido encontrada uma solução
14
Expressões Booleanas ... encontrada = 0 vi = vmin; while vi <= vmax & !encontrada alfa = amin; while alfa <= amax & !encontrada ka = kmin; while ka <= kmax & !encontrada [x, y, t] = tiro(vi,alfa,ka); if x > xmin & y > ymin v = vi; a = alfa; k = ka; encontrada = 1 endif; ka = ka + 0.1; endwhile; alfa = alfa + 1; endwhile; vi = vi + 1; endwhile; ...
15
Expressões Booleanas
• Expressões booleanas podem ser construidas recursivamente a partir de outras mais simples com os operadores booleanos de
– Conjunção, “e” ou “and”, expressa como & em OCTAVE
– Disjunção, “ou” ou “or”, expressa como | em OCTAVE
– Negação, “não” ou “not”, expressa como ! em OCTAVE
• As variáveis booleanas podem tomar os valores verdade ou falso. Em OCTAVE, que só considera variáveis “numéricas”, 0 corresponde a falso e qualquer outro valor a verdade!
• De notar que uma variável booleana pode ser atribuído o valor booleano de uma comparação numérica. Por exemplo:
encontrada = (x > xmin & y > ymax)
16
Excepções (em ciclos)
• Embora as expressões booleanas sejam muito convenientes e permitam escrever programas muito compactos, neste caso a passagem de ciclos “para” para ciclos “enquanto” torna os programas menos “naturais”.
• Uma forma mais natural de expressar a intenção de descobrir a solução é indicar que se pretende percorrer todo o intervalo de possibilidades, excepto se se encontrar uma solução!
• A especificação de excepções é possível em muitas linguagens de programação. No Octave utiliza-se a instrução “break”, para se terminar excepcionalmente um ciclo.
17
Excepções (em ciclos) ... encontrada = 0; vi = vmin; while vi <= vmax & !encontrada ... if condição encontrada = 1; endif; ... vi = vi + 1; endwhile; ...
• Por exemplo,
em vez da forma
... for vi = vmin:vmax ... if condição break; endif; ... endfor; ...
pode utilizar-se a forma mais simples
18
Excepções (em ciclos)
• Infelizmente, a explicitação de excepções não conduz sempre a uma grande simplificação da especificação global do programa.
• No caso corrente, como existem três ciclos, ao sair do ciclo interno (de ka) é necessário verificar se se deve igualmente sair do ciclo intermédio (em alfa) e igualmente do ciclo externo (em vi).
• Em geral, é conveniente saber se o ciclo terminou de uma forma “normal” ou “excepcional”, pelo que é conveniente continuar a utilizar uma variável booleana para o efeito.
• Por exemplo, os três ciclos anteriores (em vi, alfa e ka) podem ser especificados com excepções na forma
19
Excepções (em ciclos) ... encontrada = 0 for vi = vmin: vmax for alfa = amin:amax for ka = kmin:kmax [x, y, t] = tiro(vi,alfa,ka); if x > xmin & y > ymi v = vi; a = alfa; k = ka; encontrada = 1; break; endif; endfor; if encontrada
break endif;
endfor; if encontrada break endif; endfor; ...
20
Excepções (em funções)
• Se, como é o caso corrente, existirem vários ciclos no interior de uma função, e se se detectar no interior do ciclo mais interno que o objectivo da função já foi atingido, existe um mecanismo de excepção que permite terminar a função imediatamente.
• Assim, podem imediatamente terminar-se todos os ciclos, sem se ter de verificar para cada um se o ciclo imediatamente interno terminou com uma excepção ou não.
• No entanto, poderá ter interesse informar o programa (ou função) que chama a função que pode terminar excepcionalmente, se a sua terminação foi normal ou não, o que pode ser feito através de uma variável adicional que é retornada no valor da função.
21
Trajectórias Óptimasfunction [v,a,k,descoberta,x,y]= bom_tiro(xmin,ymin,vmin,vmax,amin,amax,kmin,kmax) descoberta = 0; for vi = vmin:vmax for alfa = amin:amax for ka = kmin:0.1:kmax [x, y, t] = tiro(vi,alfa,ka); if x > xmin & y > ymin v = vi; a = alfa; k = ka; descoberta = 1; return; endif; endfor; endfor; endfor;endfunction;
22
Um Pequeno Problema• Em muitas situações, nomeadamente no corpo de ciclos, pretende-
-se trocar o valor de duas variáveis
A B• Por hipótese, façamos A = 2 e B = 5. • O problema é que ao fazer-se uma atribuição, por exemplo
A B perde-se o valor inicial de A (fica A=B=5) e a atribuição B A, mantém a situação.
• A forma mais simples de resolver este problema é utilizar uma variável secundária onde se guarda o valor inicial de A. As instruções seguintes resolvem pois o problema:
C A % C = 2A B % A = 5 B C % B = 2
top related