apostila
259 pág.

apostila

Disciplina:Algoritmos e Estrutura de Dados I542 materiais7.968 seguidores
Pré-visualização50 páginas
um valor
previamente estabelecido, isto e´, uma precisa˜o previamente determinada. Em alguns
casos, quando o ca´lculo da se´rie na˜o e´ convergente, este valor mı´nimo nunca e´ atingido,

80 CAPI´TULO 7. APLICAC¸O˜ES DAS TE´CNICAS ELEMENTARES

obrigando tambe´m o programa a testar um nu´mero ma´ximo de iterac¸o˜es. Segue a
mesma ideia discutida no caso de gerar o nu´mero a´ureo.

Suponhamos que o enunciado tivesse como condic¸a˜o de parada um destes dois
crite´rios: ou o erro e´ menor do que 10−7 ou o nu´mero ma´ximo de iterac¸o˜es e´ 50.
Se o programa sair pelo crite´rio de erro, enta˜o o valor de e foi encontrado, sena˜o,
se saiu pelo crite´rio do nu´mero ma´ximo de iterac¸o˜es, enta˜o o programa avisa que
na˜o conseguiu encontrar a soluc¸a˜o. A figura 7.6 ilustra a soluc¸a˜o para este caso. E´
importante observar que o que muda com relac¸a˜o a` primeira soluc¸a˜o e´ apenas o crite´rio
de parada. Os ca´lculos internos sa˜o os mesmos.

const itmax=50; precisao=0.0001;
begin

e:= 0;
eanterior:= −1;
fat:= 1;
i := 1;
while ( i <= itmax) and (e − eanterior > precisao) do
begin

novotermo:= 1/fat ;
eanterior:= e ;
e:= e + novotermo;
fat:= i∗fat ;
i := i + 1;

end;
i f i >= itmax then

writeln (’solucao nao encontrada’)
else

writeln (’e= ’ ,e) ;
end.

Figura 7.6: Ca´lculo do nu´mero neperiano.

7.3.2 Ca´lculo do seno

Problema: Calcular o valor de seno(x) pela se´rie abaixo, considerando apenas os
vinte primeiros termos:

seno(x) =
x

1!
− x

3

3!
+
x5

5!
− x

7

7!
+
x9

9!
− x

11

11!
+
x13

13!
− x

15

15!
+ . . .

Comparando esta se´rie com a do nu´mero neperiano, observamos treˆs diferenc¸as
ba´sicas: a primeira e´ o sinal, que a cada termo muda de positivo para negativo e vice-
e-versa e antes era sempre positivo; a segunda e´ o numerador, que antes era a constante
1, agora e´ uma poteˆncia de x; a terceira e´ que os fatoriais na˜o sa˜o consecutivos em
cada termo, aumentam de dois em dois.

7.3. SE´RIES 81

Trataremos de cada caso separadamente, construindo a soluc¸a˜o para o seno base-
ada na do nu´mero neperiano. Vamos tratar primeiro o mais simples, que e´ a questa˜o
dos sinais. Considere a seguinte se´rie:

tmp =
1

0!
− 1

1!
+

1

2!
− 1

3!
+

1

4!
− 1

5!
+

1

6!
− 1

7!
+ . . .

O algoritmo da figura 7.7 modifica o anterior pela introduc¸a˜o de uma nova varia´vel
que controla a mudanc¸a do sinal, produzindo como sa´ıda o ca´lculo da func¸a˜o tmp.

const itmax=20;
begin

seno:= 0;
fat:= 1;
sinal:= 1;
i := 1;
while i <= itmax do
begin

novotermo:= 1/fat ;
seno:= seno + sinal∗novotermo;
sinal:= −sinal ; (∗ nova variavel para sinal trocado ∗)
fat:= i∗fat ;
i := i + 1;

end;
writeln (’tmp= ’ ,seno) ;

end.

Figura 7.7: Se´rie com troca de sinais.

Agora vamos corrigir o denominador, obtendo a seguinte se´rie:

tmp2 =
1

1!
− 1

3!
+

1

5!
− 1

7!
+

1

9!
− 1

11!
+

1

13!
− 1

15!
+ . . .

A atualizac¸a˜o da varia´vel fat deve ser modificada, conforme apontado na fi-
gura 7.8:

Agora so´ resta a atualizac¸a˜o correta do numerador, que depende da leitura de um
valor x do teclado. Uma varia´vel adicional conte´m o valor de x2, para evitar ca´lculos
redundantes. O programa ilustrado na figura 7.9 implementa corretamente o ca´lculo
do seno(x) para um x dado em radianos.

Existem va´rias outras se´ries que podem ser implementadas com estas mesmas
ideias, vamos deixar isto como exerc´ıcio. Basicamente, basta o estudante observar
como os numeradores e denominadores podem ser atualizados em func¸a˜o do termo
anteriormente calculado.

82 CAPI´TULO 7. APLICAC¸O˜ES DAS TE´CNICAS ELEMENTARES

const itmax=20;
begin

seno:= 0;
fat:= 1;
sinal:= 1;
i := 1;
while i <= itmax do
begin

novotermo:= 1/fat ;
seno:= seno + sinal∗novotermo;
fat:= 2∗ i∗(2∗ i+1)∗fat ; (∗ esta eh a princial modificacao ∗)
sinal:= −sinal ;
i := i + 1;

end;
writeln (’tmp2= ’ ,seno) ;

end.

Figura 7.8: Se´rie com troca de sinais e fatorais no denominador corrigidos.

const itmax=20;
begin

seno:= 0;
fat:= 1;
sinal:= 1;
read (x) ;
x quadrado:= x∗x;
numerador:= x;
i:= 1;
while i <= itmax do
begin

novotermo:= numerador/fat ; (∗ atualiza o termo ∗)
seno:= seno + sinal∗novotermo;
numerador:= numerador∗x quadrado; (∗ atualiza o numerador ∗)
fat:= 2∗ i∗(2∗ i+1)∗fat ;
sinal:= −sinal ;
i := i + 1;

end;
writeln (’seno(’ ,x,’)= ’ ,seno) ;

end.

Figura 7.9: Ca´lculo do seno de x.

7.4. NU´MEROS PRIMOS 83

7.4 Nu´meros primos

Este e´ um dos mais completos problemas desta parte inicial da disciplina. A soluc¸a˜o
dele envolve diversos conceitos aprendidos e, de certa forma, permite o estabelecimento
de um ponto de checagem no aprendizado.

Problema: Dado um nu´mero natural n, determinar se ele e´ primo.

Nu´meros naturais primos sa˜o aqueles que sa˜o divis´ıveis apenas por ele mesmo e
por 1. Em outras palavras, se n e´ um nu´mero natural, enta˜o ele e´ primo se, e somente
se, na˜o existe outro nu´mero 1 < p < n que divida n.

Os nu´meros primos sa˜o de particular interesse em computac¸a˜o, sobretudo nos dias
de hoje, pois esta˜o por tra´s dos principais algoritmos de criptografia e transmissa˜o
segura na Internet. Nesta sec¸a˜o vamos estudar alguns algoritmos para se determinar
se um nu´mero e´ ou na˜o primo.

Aplicando-se diretamente a definic¸a˜o, temos que verificar se algum nu´mero entre
2 e n− 1 divide n. Se p divide n enta˜o o resultado da operac¸a˜o nmod p e´ zero.

O primeiro algoritmo, apresentado na figura 7.10, e´ bastante simples: basta variar
p de 2 ate´ n− 1 e contar todos os valores para os quais p divide n. Se a contagem for
zero, o nu´mero na˜o tem divisores no intervalo e e´ portanto primo. Sena˜o na˜o e´.

begin
read (n) ;
cont:= 0; (∗ contador de divisores de n ∗)
i := 2;
while i <= n−1 do
begin

if n mod i = 0 then
cont:= cont + 1; (∗ achou um divisor ∗)

i := i + 1;
end;
i f cont = 0 then

writeln (n,’ eh primo’)
end.

Figura 7.10: Verifica se n e´ primo contando os divisores.

Este algoritmo e´ bom para se determinar quantos divisores primos um dado
nu´mero tem, mas na˜o e´ eficiente para este problema pois basta saber se existe pelo
menos um divisor. Logo, basta parar logo apo´s o primeiro divisor ter sido encontrado.

A te´cnica utilizada e´ baseada em uma varia´vel booleana inicializada como sendo
verdadeira. O algoritmo “chuta” que n e´ primo mas, em seguida, se os ca´lculos
mostrarem que o chute estava errado, a informac¸a˜o e´ corrigida.

O lac¸o principal do programa deve ter duas condic¸o˜es de parada: (1) termina
quando um divisor foi encontrado; (2) termina quando nenhum divisor foi encontrado,
isto e´, quando i ultrapassou n − 1. Um teste na sa´ıda do lac¸o encontra o motivo da
sa´ıda e imprime a resposta correta. Este algoritmo pode ser visto na figura 7.11.

84 CAPI´TULO 7. APLICAC¸O˜ES DAS TE´CNICAS ELEMENTARES

begin
read (n) ;
eh primo:= true ; (∗ inicia chutando que n eh primo ∗)
i := 2;
while ( i <= n−1) and eh primo do
begin

if n mod i = 0 then
eh primo:= false ; (∗ se nao for , corrige ∗)

i := i + 1;
end;
i f eh primo then

writeln (n,’ eh primo’)
end.

Figura 7.11: Testa se n e´ primo parando no primeiro divisor.

A ana´lise deste algoritmo deve ser feita em duas situac¸o˜es: (1) no pior caso, aquele
em que o nu´mero e´ primo; (2) no melhor caso, aquele em que o nu´mero na˜o e´ primo,
de prefereˆncia um primo bem baixo.

No segundo caso, o algoritmo vai terminar bem ra´pido. No outro, ele vai testar
todas as possibilidades de ı´mpares. Mas o caso o´timo e´ raro. De fato, nos problemas
envolvendo criptografia, estes nu´meros primos tem duzentos ou mais d´ıgitos. Isto
pode fazer com que o computador fique bastante tempo processando a informac¸a˜o.

Percebemos enta˜o que se o nu´mero for par enta˜o so´ tem uma chance dele ser
tambe´m