1. Um estudante codificou uma função em python que busca encontrar o ponto fixo de uma função matemática (o valor x^{*} tal que x^{*}=f\left(x^{*}\right) ) a partir de uma determinada condição inicial dada pelo usuário (x0). No entanto, ele cometeu um erro no código inicial, mostrado abaixo. Identifique o erro e corrija-o, mantendo o uso do laço while. Para corrigir o código, você não precisa saber exatamente o que faz a função f.
def ponto_fixo(f, x0):
    x_p = x0
    x_prox = f(x_p)
    while abs(x_prox - x_p) > 0.001:
        x_prox = f(x_p)
        x_p = x_prox
    return x_prox

Passo 1

O que o enunciado pede e o que nos foi dado:
  • Precisamos identificar e corrigir um erro num trecho de código Python que tenta encontrar um ponto fixo, ou seja, um valor x^{*} tal que x^{*}=f\left(x^{*}\right), a partir de uma condição inicial x_{0}.
  • O código original é:
def ponto_fixo(f, x0):
    x_p = x0
    x_prox = f(x_p)
    while abs(x_prox - x_p) > 0.001:
        x_prox = f(x_p)
        x_p = x_prox
    return x_prox
  • Restrições importantes: manter o uso do laço \verb|while|; não precisamos saber a forma exata de f.
  • Critério de parada usado no código: a diferença entre duas iterações consecutivas deve ficar menor que a tolerância 0,001 (ou seja, parar quando |x_{n+1}-x_n|\leq 0,001).

Passo 2

O que é a iteração de ponto fixo e qual a forma correta do algoritmo:
  • A ideia da iteração de ponto fixo é construir uma sequência \{x_n\} definida por
x_{n+1} = f(x_n),
com x_0 dado pelo usuário, e continuar aplicando f até que a diferença entre duas iterações consecutivas seja pequena: |x_{n+1}-x_n| < \text{tol}.
  • As variáveis:
    • x_n é a aproximação atual.
    • x_{n+1} (ou, no código, \verb|x_prox|) é a próxima aproximação gerada por \,f(x_n).
    • \text{tol} é a tolerância, aqui \,0,001.
  • Pseudocódigo padrão (conceito):
    1. definir x \leftarrow x_0
    2. calcular x_{\text{next}} \leftarrow f(x)
    3. enquanto |x_{\text{next}} - x| > \text{tol}: atualizar x \leftarrow x_{\text{next}} e x_{\text{next}} \leftarrow f(x)
    4. devolver aproxim. x_{\text{next}} (ou x)
Explicação didática: primeiro calculamos a próxima aproximação a partir da atual; só então comparamos para ver se convergimos; se não, avançamos a iteração atual para o próximo e repetimos.

Passo 3

Análise detalhada do erro no código original (linha a linha) e por que ele falha:
  • Inicialmente o código faz:
    • \verb|x_p = x0|
    • \verb|x_prox = f(x_p)| (ok: calcula f(x_0))
  • A condição do while é correta em intenção: \verb|while abs(x_prox - x_p) > 0.001:| corresponde a |x_{n+1}-x_n|>\text{tol}|.
  • Dentro do laço o código original faz, na ordem:
    1. \verb|x_prox = f(x_p)|
    2. \verb|x_p = x_prox|
  • Problema: a primeira linha dentro do laço recalcula \verb|x_prox| usando o mesmo \verb|x_p| que já existia no começo da iteração; em seguida a segunda linha copia esse mesmo valor para \verb|x_p|. Ou seja, após a primeira iteração ficamos com \verb|x_prox == x_p|, logo \verb|abs(x_prox - x_p)| passa a ser \,0 e o laço termina imediatamente. Isso faz com que o algoritmo faça no máximo uma atualização séria e pare prematuramente — ele não realiza a sequência correta x_0 \to x_1 \to x_2 \to \dots.
  • Exemplo numérico ilustrativo (para entender o bug): suponha x_0=1 e f(x)=x+1 (só para ilustrar a execução do código). Então:
    • fora do laço: \;x_p=1,\;x_prox=f(1)=2.
    • condição |2-1|>0,001 é verdadeira, entra no laço.
    • dentro do laço recalcula \;x_prox=f(1)=2 e então faz \;x_p=2.
    • volta ao teste e agora |2-2|=0\leq0,001, para. O código retorna 2. Mas o correto para a iteração seria ter calculado x_2=f(2)=3 na próxima iteração; ou seja, a sequência não foi avançada corretamente. Portanto o laço está mal organizado.

Passo 4

Como corrigir (explicação da ordem correta das atualizações) — a regra simples:
  • Ordem correta dentro do laço: primeiro atualizar a aproximação atual com o valor previamente calculado, e só depois calcular a próxima aproximação. Em código:
    1. \verb|x_p = x_prox| # avançar: x_n <- x_{n+1} anterior
    2. \verb|x_prox = f(x_p)| # calcular nova x_{n+1}
  • Com essa ordem, a condição \verb|abs(x_prox - x_p) > tol| passa a comparar a diferença entre duas iterações consecutivas reais: a que acabou de ser calculada e a anterior. Assim a sequência x_0, x_1, x_2,\dots é construída corretamente.

Passo 5

Pequena observação sobre variantes equivalentes (útil na prova):
  • Outra forma comum (equivalente) é calcular a próxima aproximação, testar a diferença e, se já estiver dentro da tolerância, parar; caso contrário, avançar a iteração. Em pseudocódigo:
    • repetir:
      • x_{\text{next}} \leftarrow f(x)
      • se |x_{\text{next}}-x| \le \text{tol} então pare e retorne x_{\text{next}}
      • senão x \leftarrow x_{\text{next}}
    • fim repetir
  • Ambas as formas são válidas; eu escolhi manter a estrutura original com a condição no while, apenas corrigindo a ordem das atualizações dentro do laço (isso atende ao pedido do enunciado).

Passo 6

Código corrigido (explicação do que mudei):
  • Mudei apenas a ordem das duas linhas dentro do laço: primeiro \verb|x_p = x_prox| e depois \verb|x_prox = f(x_p)|. Mantive a condição do while e a tolerância \,0,001.
  • Isso garante que a cada iteração usamos o último \verb|x_prox| como o novo \verb|x_p| e então computamos a próxima aproximação corretamente.

Passo 7

Código final corrigido (pronto para ser usado):

Resposta

def ponto_fixo(f, x0):
x_p = x0
x_prox = f(x_p)
while abs(x_prox - x_p) > 0.001:
x_p = x_prox
x_prox = f(x_p)
return x_prox

Exercícios relacionados