Lista 02 · Diferenças finitas¶
Acompanha o capítulo 2. O primeiro exercício é à mão, como a parte em papel da prova. Os outros pedem funções curtas: cada uma é a fórmula do quadro, escrita em Python.
Como esta lista funciona
Abra o caderno no Colab, escreva a sua solução no lugar do # TODO e rode a
célula de teste logo abaixo. Ela mesma diz o que passou e o que falhou — você
não precisa esperar correção de ninguém.
O código de cada exercício também está aqui embaixo, caso você prefira colar num editor local. Os testes comparam números com tolerância.
Exercícios marcados com ✏️ são à mão, no papel, com 4 casas decimais — como na parte em papel das avaliações.
Exercício 01¶
✏️ À mão. Seja \(f(x) = 2x^2 - 5x + 1\). Com \(h = 0{,}5\), calcule uma aproximação de \(f'(2)\) pelas diferenças
a) progressiva; b) regressiva; c) central.
d) Derive \(f\) à mão e calcule o erro relativo percentual de cada aproximação.
e) Uma das três acertou em cheio. Use a dedução por Taylor para explicar por quê — a resposta não é "sorte".
Exercício 02¶
Escreva central(f, x, h), que devolve a aproximação de \(f'(x)\) pela
diferença central:
f é uma função (o nome dela, sem parênteses).
def central(f, x, h):
"""Derivada de f em x pela diferença central, com passo h."""
# TODO: a fórmula tem f(x + h), f(x - h) e 2 * h entre parênteses
pass
# --- testes (não altere) ---
def cubo_ex02(x):
return x**3
def reta_ex02(x):
return 7 * x - 2
assert abs(central(cubo_ex02, 2, 0.1) - 12.01) < 1e-9, "x**3 em x = 2 com h = 0.1"
assert abs(central(reta_ex02, 5, 0.3) - 7) < 1e-9, "a derivada de uma reta é a inclinação"
assert abs(central(cubo_ex02, -1, 0.01) - 3.0001) < 1e-9, "x**3 em x = -1"
print("Exercício 02: todos os testes passaram!")
Exercício 03¶
Escreva erro_relativo(aprox, exato), que devolve o erro relativo
percentual \(\left|\dfrac{\text{aprox} - \text{exato}}{\text{exato}}\right| \times 100\).
def erro_relativo(aprox, exato):
"""Erro relativo percentual entre a aproximação e o valor exato."""
# TODO: use abs(...) e não esqueça o * 100
pass
# --- testes (não altere) ---
assert abs(erro_relativo(4, 3) - 100 / 3) < 1e-9
assert abs(erro_relativo(2.9, 3) - 10 / 3) < 1e-9, "o erro é sempre positivo"
assert abs(erro_relativo(-0.5, -0.4) - 25) < 1e-9, "exato negativo: o erro continua positivo"
assert erro_relativo(7, 7) == 0
print("Exercício 03: todos os testes passaram!")
Exercício 04¶
Farmacologia. Depois de um comprimido, a concentração do remédio no sangue (em mg/L) segue, \(t\) horas depois,
Ela sobe enquanto o remédio é absorvido e desce enquanto o corpo o elimina.
Escreva taxa_concentracao(t, h), que devolve a taxa de variação de \(C\)
(mg/L por hora) no instante t, pela diferença central com passo h.
taxa_concentracao(1, 0.01) # -> ≈ 3.419 (subindo)
taxa_concentracao(5, 0.01) # -> ≈ -1.455 (descendo)
Em que instante, aproximadamente, a taxa passa de positiva para negativa? O que isso significa para o paciente? (Guarde a resposta: é o problema de raiz da Unidade 3.)
import numpy as np
def C(t):
"""Concentração (mg/L) t horas depois do comprimido. JÁ ESCRITA."""
return 20 * (np.exp(-0.2 * t) - np.exp(-1.5 * t))
def taxa_concentracao(t, h):
"""Taxa de variação de C em t (mg/L por hora), pela central."""
# TODO: a mesma fórmula do ex02, com C no lugar de f
pass
# --- testes (não altere) ---
import numpy as np
def exata_ex04(t):
return 20 * (-0.2 * np.exp(-0.2 * t) + 1.5 * np.exp(-1.5 * t))
assert abs(taxa_concentracao(1, 0.01) - exata_ex04(1)) < 1e-3, "em t = 1 h a concentração sobe"
assert abs(taxa_concentracao(5, 0.01) - exata_ex04(5)) < 1e-3, "em t = 5 h ela desce"
assert taxa_concentracao(1, 0.01) > 0 and taxa_concentracao(5, 0.01) < 0
print("Exercício 04: todos os testes passaram!")
Exercício 05¶
Escreva segunda_central(f, x, h), que aproxima \(f''(x)\) por
Aplicação — física. A posição de um carro num teste de frenagem é \(s(t) = 30t - 2{,}5t^2\) metros. A aceleração é \(s''(t)\). Quanto ela vale? Por que a fórmula acerta exatamente, qualquer que seja \(h\)?
def segunda_central(f, x, h):
"""Segunda derivada de f em x, com passo h (pesos 1, -2, 1)."""
# TODO: o denominador é h ao quadrado
pass
# --- testes (não altere) ---
import numpy as np
def posicao_ex05(t):
return 30 * t - 2.5 * t**2
assert abs(segunda_central(posicao_ex05, 3, 0.5) - (-5)) < 1e-9, "a aceleração do carro é -5 m/s²"
assert abs(segunda_central(np.sin, 1.0, 0.001) - (-np.sin(1.0))) < 1e-5, "a segunda derivada de sen é -sen"
assert abs(segunda_central(np.exp, 0.0, 0.01) - 1) < 1e-4
print("Exercício 05: todos os testes passaram!")
Exercício 06¶
Veja a ordem com os próprios olhos. Escreva
razao_dos_erros(f, derivada_exata, x, h), que calcula o erro absoluto da
diferença central com passo h e com passo h / 2, e devolve a razão
erro(h) / erro(h/2).
A dedução por Taylor promete que a central é \(O(h^2)\). Que número a razão deve dar? Teste com \(e^x\) em \(x = 0\) e \(h = 0{,}1\).
def central(f, x, h):
"""Diferença central. JÁ ESCRITA."""
return (f(x + h) - f(x - h)) / (2 * h)
def razao_dos_erros(f, derivada_exata, x, h):
"""Erro da central com h dividido pelo erro com h/2."""
# TODO: dois erros absolutos (abs), depois a divisão de um pelo outro
pass
# --- testes (não altere) ---
import numpy as np
r = razao_dos_erros(np.exp, np.exp(0.0), 0.0, 0.1)
assert abs(r - 4) < 0.01, f"a central é O(h²): h pela metade, erro 4 vezes menor (deu {r})"
r = razao_dos_erros(np.sin, np.cos(1.0), 1.0, 0.05)
assert abs(r - 4) < 0.01
print("Exercício 06: todos os testes passaram!")
Exercício 07¶
O melhor \(h\). Escreva melhor_h(f, derivada_exata, x), que testa a
diferença central com \(h = 10^{-1}, 10^{-2}, \ldots, 10^{-15}\) e devolve o
\(h\) que deu o menor erro absoluto.
Use o padrão "extremo": comece com o primeiro \(h\) como candidato e troque sempre que achar um erro menor.
Teste com \(f(x) = x^3\) em \(x = 1\) (a derivada exata é 3). O melhor \(h\) é \(10^{-15}\)? Por quê?
def central(f, x, h):
"""Diferença central. JÁ ESCRITA."""
return (f(x + h) - f(x - h)) / (2 * h)
def melhor_h(f, derivada_exata, x):
"""O h, entre 1e-1 e 1e-15, com o menor erro da central."""
# TODO: laço com k de 1 a 15, h = 10.0**(-k); guarde o melhor h e o menor erro
pass
# --- testes (não altere) ---
def cubo_ex07(x):
return x**3
h = melhor_h(cubo_ex07, 3.0, 1.0)
assert h is not None, "faltou o return?"
assert 1e-7 <= h <= 1e-4, f"o melhor h fica no fundo do V, longe das pontas (deu {h})"
assert h == 1e-05 or h == 1e-06, f"deu {h}"
print("Exercício 07: todos os testes passaram!")
Exercício 08¶
Economia — vale a pena a encomenda extra? Uma padaria industrial tem custo diário \(C(q) = 800 + 1{,}2q + 0{,}0004q^2\) reais para produzir \(q\) pães. Um cliente oferece comprar pães extras por um preço fixo. Vale a pena aceitar se o preço for maior que o custo marginal \(C'(q)\) na produção atual.
Escreva vale_a_pena(preco, q), que devolve True ou False. As funções
custo e central já estão escritas: o trabalho é compô-las. Use
\(h = 1\) (um pão).
vale_a_pena(2.00, 500) # -> True (custo marginal: R$ 1,60)
vale_a_pena(2.00, 1500) # -> False (custo marginal: R$ 2,40)
def custo(q):
"""Custo diário (R$) para produzir q pães. JÁ ESCRITA."""
return 800 + 1.2 * q + 0.0004 * q**2
def central(f, x, h):
"""Diferença central. JÁ ESCRITA."""
return (f(x + h) - f(x - h)) / (2 * h)
def vale_a_pena(preco, q):
"""True se o preço oferecido supera o custo marginal em q."""
# TODO: custo marginal = central(custo, q, 1); compare com o preço
pass
# --- testes (não altere) ---
assert vale_a_pena(2.00, 500) is True, "em 500 pães o custo marginal é R$ 1,60"
assert vale_a_pena(2.00, 1500) is False, "em 1500 pães o custo marginal é R$ 2,40"
assert vale_a_pena(1.61, 500) is True
assert vale_a_pena(1.59, 500) is False
print("Exercício 08: todos os testes passaram!")