Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Estruturas de Repetição Iterativas

Authors
Affiliations
University of São Paulo
University of São Paulo

Até agora, vimos que o computador é muito bom para fazer cálculos e repetições. Fizemos essas repetições com funções recursivas, que chamam a si mesmas para resolver problemas menores. Agora vamos ver uma forma alternativa de repetir: a abordagem iterativa.

Introdução ao while

A estrutura while é uma das formas mais básicas de criar laços (em inglês, loops) em programação. Ela permite repetir um bloco de código enquanto uma condição for verdadeira. A sintaxe básica do while em Julia é:

while condição
    # Bloco de código a ser repetido
end

O funcionamento do while segue estes passos:

  1. A condição é avaliada

  2. Se a condição for verdadeira, o bloco de código é executado

  3. Após a execução do bloco, a condição é avaliada novamente

  4. Este ciclo continua até que a condição se torne falsa

É importante lembrar que, para evitar um loop infinito (um laço que nunca termina), algo relacionado à condição precisa mudar dentro do bloco de código.

Vamos começar com um exemplo simples: contagem regressiva.

function contagem_regressiva(n)
    while n > 0
        println(n)
        n = n - 1  # Esta linha é essencial para evitar um loop infinito
    end
    println("Fim!")
end

contagem_regressiva(5)
5
4
3
2
1
Fim!

Neste exemplo, a condição n > 0 é inicialmente verdadeira (assumindo que n começa com um valor positivo). O bloco de código imprime o valor atual de n e, em seguida, decrementa n em 1. Eventualmente, n chegará a zero, tornando a condição falsa e encerrando o loop.

Comparando Recursão e Iteração

Para entender melhor a diferença entre recursão e iteração, vamos reescrever algumas funções que implementamos anteriormente usando recursão.

Contagem Regressiva

Primeiro, vamos relembrar a versão recursiva da contagem regressiva:

function contagem_recursiva(n)
    if n <= 0
        println("Fim!")
    else
        println(n)
        contagem_recursiva(n - 1)
    end
end

contagem_recursiva(5)
5
4
3
2
1
Fim!

Comparando as duas implementações, podemos observar que:

Ambas as versões produzem o mesmo resultado, mas com abordagens diferentes.

Soma dos Primeiros N Números

Vamos implementar uma função que calcula a soma dos primeiros n números inteiros positivos (1 + 2 + ... + n), usando tanto recursão quanto while.

Versão recursiva:

function soma_recursiva(n)
    if n <= 0
        return 0
    else
        return n + soma_recursiva(n - 1)
    end
end

println("Soma dos primeiros 5 números (recursiva): ", soma_recursiva(5))
Soma dos primeiros 5 números (recursiva): 15

Versão com while:

function soma_while(n)
    soma = 0
    i = 1
    
    while i <= n
        soma = soma + i
        i = i + 1
    end
    
    return soma
end

println("Soma dos primeiros 5 números (while): ", soma_while(5))
Soma dos primeiros 5 números (while): 15

Na versão recursiva, temos um caso base explícito (n <= 0) e uma chamada recursiva que reduz o problema. Na versão com while, utilizamos uma variável de controle i que é incrementada a cada iteração, e uma variável acumuladora soma que armazena o resultado parcial.

Calculando Séries Matemáticas

As estruturas de repetição são especialmente úteis para calcular somas de séries matemáticas. Vamos implementar uma função para calcular a aproximação do seno usando a série de Taylor:

sin⁡(x)=x−x33!+x55!−x77!+…\sin(x) = x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} + \ldots

Esta série pode ser representada como:

sin⁡(x)=∑n=0∞(−1)n⋅x2n+1(2n+1)!\sin(x) = \sum_{n=0}^{\infty} \frac{(-1)^n \cdot x^{2n+1}}{(2n+1)!}

Implementação usando while:

function sin_taylor(x, termos = 10)
    resultado = 0.0
    termo = x
    i = 0
    
    while i < termos
        # Adicionamos o termo atual à soma
        resultado = resultado + termo
        
        # Calculamos o próximo termo
        i = i + 1
        termo = -termo * x * x / ((2 * i) * (2 * i + 1))
    end
    
    return resultado
end

# Teste com π/6 (30 graus), cujo seno é 0.5
println("sin(π/6) ≈ ", sin_taylor(π/6))
println("sin(π/6) exato: ", sin(π/6))
sin(π/6) ≈ 0.49999999999999994
sin(π/6) exato: 
0.49999999999999994

Note que o while permite controlar com precisão o número de termos da série que queremos calcular.

Vamos comparar com uma implementação recursiva:

function sin_taylor_recursivo(x, i = 0, termos = 10, termo = x, resultado = 0.0)
    if i >= termos
        return resultado
    else
        # Adicionamos o termo atual à soma
        novo_resultado = resultado + termo
        
        # Calculamos o próximo termo
        novo_i = i + 1
        novo_termo = -termo * x * x / ((2 * novo_i) * (2 * novo_i + 1))
        
        return sin_taylor_recursivo(x, novo_i, termos, novo_termo, novo_resultado)
    end
end

println("sin(π/6) recursivo ≈ ", sin_taylor_recursivo(π/6))
sin(π/6) recursivo ≈ 0.49999999999999994

A versão recursiva é mais complexa, pois precisamos passar vários parâmetros extras para manter o estado entre as chamadas. A versão com while é mais clara e direta neste caso.

Quando Usar Recursão e Iteração?

Tanto a recursão quanto a iteração podem ser usadas para resolver problemas de repetição, cada uma com seus pontos fortes:

Vantagens da iteração

Vantagens da recursão

Uma regra prática é:

Verifique seu Aprendizado

  1. Qual é a diferença entre usar recursão e iteração para repetições?

  2. Implemente uma função que conte o número de dígitos em um número inteiro usando a estrutura while.

  3. Dado um número inteiro, escreva uma função que inverta seus dígitos (por exemplo, 123 se tornaria 321).

Explore por Conta Própria

  1. Pesquise sobre otimização de laços (loop unrolling) e tente aplicar esse conceito em uma função com while.