- Um estudante codificou uma função em python que busca encontrar o ponto fixo de uma função matemática (o valor
tal que
) 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
.
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
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_proxPasso 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
tal que , a partir de uma condição inicial . - 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
. - Critério de parada usado no código: a diferença entre duas iterações consecutivas deve ficar menor que a tolerância
(ou seja, parar quando ).
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
definida por
com
dado pelo usuário, e continuar aplicando
até que a diferença entre duas iterações consecutivas seja pequena:
.
- As variáveis:
-
é a aproximação atual. -
(ou, no código, \verb|x_prox|) é a próxima aproximação gerada por . -
é a tolerância, aqui .
-
- Pseudocódigo padrão (conceito):
- definir
- calcular
- enquanto
: atualizar e - devolver aproxim.
(ou )
- definir
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
)
- A condição do while é correta em intenção: \verb|while abs(x_prox - x_p) > 0.001:| corresponde a
. - Dentro do laço o código original faz, na ordem:
- \verb|x_prox = f(x_p)|
- \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
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 . - Exemplo numérico ilustrativo (para entender o bug): suponha
e (só para ilustrar a execução do código). Então: - fora do laço:
. - condição
é verdadeira, entra no laço. - dentro do laço recalcula
e então faz . - volta ao teste e agora
, para. O código retorna . Mas o correto para a iteração seria ter calculado na próxima iteração; ou seja, a sequência não foi avançada corretamente. Portanto o laço está mal organizado.
- fora do laço:
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:
- \verb|x_p = x_prox| # avançar: x_n <- x_{n+1} anterior
- \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
é 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:
-
- se
então pare e retorne - senão
-
- fim repetir
- 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
. - 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
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