Introdução à Programação
Um enfoque orientado a construção de
modelos em programas baseados em objetos
Gustavo Motta
Departamento de Informática - UFPB
6. Comandos iterativos e recursão
► Comandos
iterativos ou de repetição
 Definição
comando iterativo (também chamado de laço) tem um
subcomando (o corpo do laço) que é executado repetidamente
e uma cláusula que determina quando a repetição cessará
► Um
 Essencial para uma linguagem ser universal
 Necessários em muitos modelos e aplicações
► Calcular
a média das notas de todos os alunos de uma turma
► Comparar
a seqüência de caracteres em um string que
representa parte de um DNA com outra, caractere por
caractere, do primeiro até o último
► Repetir
a leitura da senha de um usuário enquanto ela não
estiver correta
(C) 2008 Gustavo Motta
2
6. Comandos iterativos e recursão
► Comandos
iterativos ou de repetição
 Modalidades
► Comandos
de iteração indefinida
 Aqueles nos quais o número de iterações não é determinado
previamente
 Depende de uma condição de repetição
► Enquanto
não alcançar a última linha do arquivo, continue
lendo a próxima linha para imprimi-la
 Em Java, são os comandos while e do-while
► Comandos
de iteração definida
 Aqueles nos quais o número de iterações é sabido antecipadamente
 Caracterizado pelo uso de uma variável de controle, denominada de
contador do laço
► Some
os valores de uma seqüência de números, desde a
primeira posição, até a centésima
(C) 2008 Gustavo Motta
 Em Java, é o comando for
3
6. Comandos iterativos e recursão
►O
comando while
► while
(expressão-lógica)
subcomando;
► while
(expressão-lógica) {
subcomando_1;
subcomando_2;
...
subcomando_n;
}
 A avaliação da expressão-lógica determina a condição
de repetição. Caso true, o subcomando (ou o bloco de
subcomandos) é executado e a condição é reavaliada
► Enquanto
► Quando
a condição for true, o subcomando é executado
a condição for false, o comando while é encerrado e
(C) 2008 Gustavo Motta
4
o próximo comando é executado
6. Comandos iterativos e recursão
►O
comando while
 Exemplo: calcular o somatório dos primeiros N números
inteiros positivos
Memória
n
1
int somatório(int n) {
int soma = 0, proximoInt = 1;
2
soma
while (proximoInt <= n) {
soma = soma + proximoInt;
3 proximoInt
proximoInt = proximoInt + 1;
}
return soma;
}
...
System.out.println(“Somátório de 5: ”+somatório(5));
(C) 2008
Gustavo Motta
Somatório de 5:
15
5
10
15
0
1
3
6
1
2
3
4
5
6
5
6. Comandos iterativos e recursão
►O
comando while
 usar
Recomendações
de while
verificação
Pode-se
o próprio comando
para obrigar o usuário a entrar
Verificar
se inteiros
a condição
de repetição inicial do while permite a
somente ►
com
números
positivos
entrada no laço de forma correta
 Caso
a condição
inicial
seja false, o subcomando ou bloco de
Scanner entrada
= new
Scanner
(System.in);
subcomandos
do while não será executado nem mesmo uma vez
int intPositive
= entrada.nextInt();
while (intPositive
<= o0)valor
{ de n seja zero ou negativo, a condição inicial é
► Caso
System.out.println("===O
numero
nao pode ser
zero===");
false, bloco
de subcomandos
do negativo
while do ou
exemplo
anterior
intPositive = não
entrada.nextInt();
é executado nenhuma vez e o resultado do somatório é 0
}
 Nesta versão abaixo do exemplo anterior, o bloco de subcomandos
do laço nunca é executado porque a condição sempre é false
int soma = demowhile.somatório(intPositive);
int somatório(int n) {
System.out.println("Somatorio
de "+intPositive+":
"+soma);
int soma = 0, proximoInt
= n + 1;
while (proximoInt <= n) {
soma = soma + proximoInt;
proximoInt = proximoInt + 1;
}
(C) 2008 Gustavo Motta
return soma;
}
6
6. Comandos iterativos e recursão
►O
comando while
• Por exemplo,
o comando while
abaixo nunca termina porque a sua condição
 Recomendações
de verificação
do sempre ►
será
verdadeira
n inicialmente
>= 1),doouwhile
seja, não
varia com
Verificar
se a(sendo
condição
de repetição
permite
o
a execução dos
subcomandos
laço
encerramento
no do
laço
de acordo com a modificação, no bloco de
subcomandos do laço, das variáveis usadas na condição
int somatório(int n) {
int soma = 0, proximoInt = 1;
 No exemplo anterior, supondo que proximoInt = 1 e que n é
while (proximoInt
<= n) {
positivo, o subcomando proximoInt = proximoInt + 1; no do laço
soma = soma
+ proximoInt;
assegura
que a condição proximoInt <= n será false numa dada
proximoInt
= proximoInt
0; o número de repetições sempre será
iteração
do while , ou+ seja,
}
finito (igual a n)
return soma;
}
 Caso a condição seja sempre true, isto é, não possa variar com a
execução sucessiva do bloco de subcomandos do while, então o
• Embora não termine
de forma
normal,
é possível
programa
continuará
executando
parainterromper
sempre, ou anormalmente
seja, o número
deloop
repetições
será infinito do sistema operacional ou
um programa (em
) com comandos
simplesmente desligando o computador,
porém
os resultados obtidos podem 7
(C) 2008 Gustavo
Motta
ser indesejáveis
6. Comandos iterativos e recursão
►O
comando while
 Recomendações de verificação
• Isto porque se o resultado não pode ser armazenado, o valor efetivamente
► Quando
se ao
tratar
de valor
números
no comando
while,
deve-se
armazenado
corresponde
menor
armazenável
(-128 no
caso do
tipo
observar
possibilidade
daoocorrência
dearmazenável
overflow
byte) adicionado
pelo a
valor
que excede
maior valor
menos 1
 Em números inteiros, o overflow ocorre quando o resultado da
valorArmazenado
= menorInteiro
(Resultadoaritmética
– maiorInteiro
– 1)número maior (ou
avaliação
de uma +expressão
é um
menor) que o maior (menor) número que pode ser representado
• Por exemplo, caso
tente
o valor 200 numa variável do tipo
numse
dado
tipoarmazenar
inteiro
short, o valor efetivamente
armazenado
será
► Por exemplo,
uma variável
do tipo byte pode armazenar
qualquer valor no intervalo -128 até +127
valorArmazenado = –128 + (200 – 127 – 1) = –56
byte contador = 127;
• É importante frisar que
o nem o compilador, nem a maquina virtual Java,
contador = (byte) (contador + 1);
acusa este tipo de erro.
System.out.println(“Contador: ”+contador);
Cabe ao programador tomar cuidado, examinando cuidadosamente os
► No
-128 é o valor
impressoem variáveis
limites máximos
e exemplo
mínimosacima,
potencialmente
assumidos
(C) 2008 Gustavo Motta
8
inteiras e sua adequação do tipo escolhido: byte, short, int ou long
6. Comandos iterativos e recursão
►O
comando while
 Recomendações de verificação
► Quando
se tratar de números no comando while, deve-se
observar a possibilidade da ocorrência de overflow
 Em números de ponto flutuante, o overflow também pode ocorrer,
mas nestes casos, a linguagem Java estabelece valores constantes
especiais para designar o infinito positivo e o infinito negativo
► Por
exemplo, ao final da execução do código abaixo
float valor = Float.MAX_VALUE;
valor = valor * 2;
System.out.println(“Valor: ” + valor);
► No
exemplo acima, Infinity é o valor impresso e
corresponde
ao
valor
da
constante
Float.POSITIVE_INFINITY
definida na classe Float da
(C) 2008 Gustavo Motta
9
biblioteca de classes de Java
6. Comandos iterativos e recursão
►O
comando while
 Recomendações de verificação
► Quando
se tratar de números de ponto flutuante no comando
while, deve-se observar a possibilidade da ocorrência de
underflow
• O compilador
arredonda para zero valores muito próximos de zero que não
 O underflow
pode
ocorrer
quando
o tipoflutuante
ponto flutuante não for
podem ser representados
num
dado
número
de ponto
capaz de representar um número muito próximo de zero
• Cabe ao programador
todas
► Portomar
exemplo,
ao as
finalprecauções
da execuçãonecessárias!
do código abaixo
float quociente = 1;
while (quociente > 0) {
System.out.println(quociente);
quociente = quociente / 2;
}
o valor da variável quociente é zero, embora devesse ser um
número muito pequeno, próximo de zero, mas não zero
(C) 2008 Gustavo Motta
10
6. Comandos iterativos e recursão
►O
comando while
 Recomendações de verificação
► Seja
cuidadoso ao usar desigualdades em condições de controle
de repetições no comando while
• Em casos como este, deve-se evitar o uso de desiguladades. O código
► Por exemplo, a execução do código abaixo
anterior pode ser reescrito da forma mais segura abaixo
float saldo = 10;
float while
saldo (saldo
= 10; != 0) {
while (saldo
>= 0) {
System.out.println(saldo);
System.out.println(saldo);
saldo = saldo – 0.1f;
saldo
= saldo – 0.1f;
}
}
nunca termina, pois devido a imprecisão na representação de
números decimais (e. g., o valor 0.1) em notação de ponto
flutuante em base binário, o valor do saldo passa de um
número positivo muito próximo de zero para um número
negativo também muito próximo a zero, mas sem ser zero,
11
como esperado(C) 2008 Gustavo Motta
6. Comandos iterativos e recursão
►O
comando while
 Comandos de iteração em Java podem ser encerrados
abruptamente, independente da condição de repetição,
com o uso do comando break
► Sempre
que um break é executado dentro de um laço, ele força
o seu encerramento imediato, seguindo o programa o fluxo
normal de execução do próximo comando após o laço
►
Por exemplo, o laço abaixo
while (true) {
String opcao = entrada.nextLine();
if (opcao.equals(“s”))
break;
System.out.println(opcao);
}
só termina quando
valor
opcao for igual a s e o valor de
(C) 2008 o
Gustavo
Motta
opcao só é impresso se ela for diferente de s
12
6. Comandos iterativos e recursão
►O
comando while
 Comandos de iteração em Java podem ser parcialmente
interrompidos com o comando continue
► Sempre
que um continue é executado dentro de um laço, ele
interrompe a execução dos subcomandos do laço nesta iteração,
a partir do próximo subcomando, voltando para a avaliação da
condição de terminação do laço
►
Por exemplo, no laço abaixo
String opcao = “a”;
while (!opcao.equals(“s”)) {
opcao = entrada.nextLine();
if (opcao.equals(“s”))
continue;
System.out.println(“Entre Opção diferente de s”);
}
o último subcomando só é executado quando a opção é
Gustavo
Motta
diferente de s.(C) 2008
Caso
contrário,
o continue força o desvio 13
do
fluxo de execução para a avaliação da condição do laço
6. Comandos iterativos e recursão
►O
comando do-while
do {
subcomando_1;
subcomando_2;
...
subcomando_n;
}
while (expressão-lógica);
 A avaliação da expressão-lógica
condição de repetição
►Enquanto
determina
a
a condição for true, o bloco de subcomandos é
executado
►Quando
a condição for false, o comando do-while é
encerrado e o próximo comando é executado
►A
diferença em relação
ao comando while é que o bloco de
(C) 2008 Gustavo Motta
14
subcomandos é, necessariamente, executado pelo menos uma vez
6. Comandos iterativos e recursão
►O
comando do-while
 Exemplo: ler a opção do menu de uma aplicação
int menuCartãoCrédito() {
int opcao = 0;
Scanner entrada = new Scanner(System.in);
do {
System.out.print(“1 - compra | 2 - paga | 3 - ver saldo | “);
System.out.println(“4 - ver bonus | 5 - encerra: ");
System.out.print("Sistema de Cartao de Credito. ”);
System.out.print("Escolha a opcao: ");
opcao = entrada.nextInt();
}
while (!(opcao > = 1 && opcao <= 5));
return opcao;
}
(C) 2008 Gustavo Motta
15
6. Comandos iterativos e recursão
► Contadores
 Contadores são variáveis que recebem um valor inicial e
que são modificadas a cada iteração de comando de
repetição de Java
► Contadores
são modificados mediante a atribuição do resultado
da avaliação de uma expressão aritmética envolvendo o próprio
contador
 soma = soma + 1;
 fatorial = fatorial * n;
 saldo = saldo – 100;
 quociente = quociente / 2;
► Java
permite a utilização de operadores
modificação de variáveis que são contadores
(C) 2008 Gustavo Motta
especiais
para
16
6. Comandos iterativos e recursão
► Contadores
 Operador ++ : quando aplicado a uma variável numérica,
incrementa o valor da variável em um
soma++;
► é o mesmo que
soma = soma + 1;
► Além
de modificar o valor, o operador ++ retorna um valor
 Caso o operador seja aplicado à direita do operando, o valor
retornado é igual ao valor da variável antes da aplicação, por
exemplo
► int resultado = 0, contador = 1;
resultado = contador++;
►o
conteúdo da variável resultado após a atribuição é 1
enquanto o conteúdo de contador é 2
 Caso o operador fosse aplicado à esquerda
► resultado
►o
= (C)++contador;
2008 Gustavo Motta
conteúdo de ambas as variáveis seria 2
17
6. Comandos iterativos e recursão
► Contadores
 Operador -- : quando aplicado a uma variável numérica,
decrementa o valor da variável em um
total--;
► é o mesmo que
total = total - 1;
► Além
de modificar o valor, o operador  retorna um valor
 Caso o operador seja aplicado à direita do operando, o valor
retornado é igual ao valor da variável antes da aplicação, por
exemplo
► int resultado = 0, total = 100;
resultado = total--;
►o
conteúdo da variável resultado após a atribuição é 100
enquanto o conteúdo de total é 99
 Caso o operador fosse aplicado à esquerda
► resultado
►o
= (C)--total;
2008 Gustavo Motta
conteúdo de ambas as variáveis seria 99
18
6. Comandos iterativos e recursão
► Contadores
 Operador += : quando aplicado a uma variável numérica,
adiciona, ao valor da variável atribuída, o valor à direita
do operando
saldo += 100;
►é
o mesmo que
saldo = saldo + 100;
 Operador -= : quando aplicado a uma variável numérica,
subtrai, do valor da variável atribuída, o valor à direita do
operando
saldo -= 50;
►é
o mesmo que
saldo = saldo -(C) 2008
50;
Gustavo Motta
19
6. Comandos iterativos e recursão
► Contadores
 Operador *= : quando aplicado a uma variável numérica,
multiplica, o valor da variável atribuída, pelo valor à
direita do operando
fatorial *= n;
►é
o mesmo que
fatorial = fatorial * n;
 Operador /= : quando aplicado a uma variável numérica,
divide, o valor da variável atribuída, pelo valor à direita do
operando
quociente /= 100;
►
o mesmo que
quociente = quociente
/ 100;
(C) 2008 Gustavo Motta
20
6. Comandos iterativos e recursão
►O
comando for
 for (inicialização; expressão-lógica; atualização)
subcomando;
 for (inicialização; expressão-lógica; atualização) {
subcomando_1;
subcomando_2;
...
subcomando_n;
}
► inicialização
atribui um valor inicial para o contador do for
► expressão-lógica
► atualização
estabelece a condição de repetição do laço
(C) 2008 Gustavo Motta
modifica
o valor do contador do for
21
6. Comandos iterativos e recursão
►O
comando for
 Exemplo: calcular o fatorial de N
Memória
n
long fatorial(int n) {
1
long fat = 1;
2
fat
fat
fat
for (int i = 1; i <= n; i++) {
fat = fat * i;
i
3
}
return fat;
}
...
System.out.println(“Fatorial de 5: ”+ fatorial(5));
Fatorial de 5: (C)120
2008 Gustavo Motta
5
120
24
6
2
1
5
3
2
1
4
22
6. Comandos iterativos e recursão
►O
comando for
 Outras formas de uso
int contador;
for (contador = 0; contador < 100; contador++) {
System.out.println(contador);
}
for (contador = 200;contador >= 0; contador -= 10) {
System.out.println(contador);
}
for (double controle = 0;controle < 0; controle += 3.5) {
System.out.println(controle);
}
(C) 2008 Gustavo Motta
23
6. Comandos iterativos e recursão
►O
comando for
 Outras formas de uso
double início
= 100;
double fim
= 200;
double incremento = 2.5;
for(;;) {
//executa para sempre
System.out.println(início);
if (início >= fim) break;
início += incremento;
}
for (contador = 0;contador < 1000; contador+=2) {
System.out.println(contador);
contador = 0;
}
(C) 2008 Gustavo Motta
24
6. Comandos iterativos e recursão
►
Recursão
 Recursão (ou recursividade)
é
uma
técnica
de
programação na qual uma
computação é definida em
termos dela mesma
long fatorial(int n) n)
{ ={4)
n
5) {
1)
2)
3)
if (n <= 1) {
return 1;
}
else {
return n * fatorial(n 1);
}
}
...
System.out.println(“Fatorial
de 5: ”+ fatorial(5));
Memória
1
n
5
2
n
4
3
n
3
4
n
2
5
n
1
Drawing
(1948),
Fatorial
5
120
* 24
fatorial(4)
4
* 6
fatorial(3)
3
de
* 5:
fatorial(2)
2
120
*Hands
fatorial(1)
1
(C) 2008 litogravura
Gustavo Motta - M C Escher
25
6. Comandos iterativos e recursão
► Recursão
 A natureza da recursividade
► Existem
maiscomo
casosuma
simples
de um para
problema,
chamados
• A recursividade
podeum
serouusada
alternativa
iteração
de casos de parada, que têm solução trivial
fatorial 1 = 1
• Em geral, é uma solução menos eficiente em termos de tempo e espaço
► Os demais casos podem ser solucionados pela substituição para
uma versão reduzida do problema, mais próximo do caso de
• Em muitos
paradacasos, oferece soluções naturais e simples para problemas
n com
= n comandos
* fatorial
n - 1
que são difíceisfatorial
de resolver
iterativos
► Num
dado momento, o problema se reduz a um caso de
parada, que permite a resolução do demais casos
n * n – 1 (C)
* 2008
n Gustavo
– 2 Motta
* ... *
1
26
6. Comandos iterativos e recursão
► Recursão
 Exemplo: torres de Hanói
► Objetivo:
mover os 5 discos do pino 1 para o pino 3,
obedecendo as seguintes regras
 Apenas um disco pode ser movido por vez, sempre o disco no
topo de algum pino
 Um disco de diâmetro maior jamais pode ser colocado sobre um
disco com diâmetro menor
1
1
2
3
4
5
2
(C) 2008 Gustavo Motta
3
27
6. Comandos iterativos e recursão
► Recursão
 Exemplo: torres de Hanói
► Solução
 Caso de parada
► Mover um único disco de um pino para outro, por exemplo,
mover o disco 1 para o pino 3
 Versão reduzida do problema
► 1. Mover 4 discos do pino 1 para o pino 2
► 2. Mover o disco 5 para o pino 3
► 3. Mover 4 discos do pino 2 para o pino 3
1
1
2
3
4
5
2
(C) 2008 Gustavo Motta
3
28
6. Comandos iterativos e recursão
► Recursão
 Exemplo: torres de Hanói
► Solução
 Refinamento do passo 1
► 1. Mover 4 discos do pino 1 para o pino 2
1.1 Mover 3 discos do pino 1 para o pino 3
1.2 Mover o disco 4 do pino 1 para o pino 2
1.3 Mover 3 discos do pino 3 para o pino 2
1
1
2
3
4
5
2
(C) 2008 Gustavo Motta
3
29
6. Comandos iterativos e recursão
► Recursão
 Exemplo: torres de Hanói
► Solução
 Refinamento do passo 1.1
► 1.1 Mover 3 discos do pino 1 para o pino 3
1.1.1 Mover 2 discos do pino 1 para o pino 2
1.1.2 Mover o disco 3 do pino 1 para o pino 3
1.1.3 Mover 2 discos do pino 2 para o pino 3
1
1
2
3
4
5
2
(C) 2008 Gustavo Motta
3
30
6. Comandos iterativos e recursão
► Recursão
 Exemplo: torres de Hanói
► Solução
 Refinamento do passo 1.1.1
► 1.1.1 Mover 2 discos do pino 1 para o pino 2
1.1.1 Mover 1 disco do pino 1 para o pino 3
1.1.2 Mover o disco 2 do pino 1 para o pino 2
1.1.3 Mover 1 disco do pino 3 para o pino 2
1
1
2
3
4
5
2
(C) 2008 Gustavo Motta
3
31
6. Comandos iterativos e recursão
► Recursão
 Exemplo: torres de Hanói
► Solução
 Versão generalizada da solução
► 1. Caso N > 0
1.1 Mover os (N – 1) primeiros discos do pino 1 para o pino 2
1.2 Mover o disco N para o pino final
1.3 Mover os (N – 1) primeiros discos do pino 2 para o pino 3
1
1
2
3
4
5
2
(C) 2008 Gustavo Motta
3
32
6. Comandos iterativos e recursão
► Recursão
 Exemplo: torres de Hanói
► Solução
em Java
void torresDeHanói(int númeroDeDiscos,
String origem,String destino,
String auxiliar) {
if (númeroDeDiscos > 0) {
torresDeHanói(númeroDeDiscos - 1,origem,auxiliar,destino);
System.out.println("Mover disco "+númeroDeDiscos+
" do "+origem+" para o"+destino);
torresDeHanói(númeroDeDiscos - 1,auxiliar,destino,origem);
}
}
(C) 2008 Gustavo Motta
33
6. Comandos iterativos e recursão
► Recursão
 Exemplo: torres de Hanói
► Solução
em Java
N
= 2
Origem "p1","p3","p2")
= “p1”
torresDeHanói(3,
Destino = “p2”
auxiliar = “p3”
torresDeHanói(1, “p1”, “p3”, “p2”)
Mover disco 2 de p1 para p2
torresDeHanói(1, “p3”, “p2”, “p1”)
return
N
= 3
Origem
= “p1”
Destino = “p3”
auxiliar = “p2”
torresDeHanói(2, “p1”, “p2”, “p3”)
Mover disco 3 de p1 para p3
torresDeHanói(2, “p2”, “p3”, “p1”)
return
N
= 1
Origem
= “p1”
Destino = “p3”
auxiliar = “p2”
Mover disco 1 de p1 para p3
return
N
= 1
Origem
= “p3”
Destino = “p2”
auxiliar = “p1”
Mover disco 1 de p3 para p2
return
N
= 1
Origem
= “p2”
Destino = “p1”
auxiliar = “p3”
Mover disco 1 de p2 para p1
return
N
= 1
Origem
= “p1”
Destino = “p3”
auxiliar = “p2”
Mover disco 1 de p1 para p3
return
N
= 2
Origem
= “p2”
Destino = “p3”
auxiliar = “p1”
torresDeHanói(1, “p2”, “p1”, “p3”)
Mover
disco
(C) 2008
Gustavo
Motta2
de p2 para p3
torresDeHanói(1, “p1”, “p3”, “p2”)
return
34
Download

6. Comandos iterativos e recursão