Quando conhecemos uma função \(f(t)\), mas não temos uma expressão analítica para sua derivada, podemos calcular uma aproximação numérica de \(f'(t_0)\) em um ponto \(t_0\).
1. A ideia básica
A derivada de uma função no ponto \(t_0\) é definida pelo limite
\[ f'(t_0) = \lim_{h \to 0} \frac{f(t_0+h)-f(t_0)}{h}. \]Na prática, escolhemos um valor pequeno para \(h\) e usamos uma fórmula de diferenças finitas para aproximar a derivada.
Entretanto, escolher \(h\) extremamente pequeno nem sempre produz um resultado melhor. Se \(h\) for pequeno demais, podem surgir erros de arredondamento causados pela subtração de números muito próximos.
2. Diferença progressiva
A fórmula mais simples é a diferença progressiva:
\[ f'(t_0) \approx \frac{f(t_0+h)-f(t_0)}{h}. \]Essa aproximação possui erro de truncamento da ordem de \(h\):
\[ \frac{f(t_0+h)-f(t_0)}{h} = f'(t_0)+\mathcal{O}(h). \]Embora seja fácil de usar, essa fórmula geralmente não é a melhor escolha quando se deseja alta acurácia.
3. Diferença central
Uma fórmula geralmente melhor é a diferença central:
\[ f'(t_0) \approx \frac{f(t_0+h)-f(t_0-h)}{2h}. \]O erro dessa fórmula é da ordem de \(h^2\):
\[ \frac{f(t_0+h)-f(t_0-h)}{2h} = f'(t_0)+\mathcal{O}(h^2). \]Isso significa que, em condições adequadas, a diferença central produz resultados significativamente mais precisos do que a diferença progressiva.
4. Fórmula de cinco pontos
Para obter uma aproximação ainda mais precisa, podemos usar a fórmula central de cinco pontos:
\[ f'(t_0) \approx \frac{ f(t_0-2h) -8f(t_0-h) +8f(t_0+h) -f(t_0+2h) }{12h}. \]O erro de truncamento dessa fórmula é da ordem de \(h^4\):
\[ f'(t_0) = \frac{ f(t_0-2h) -8f(t_0-h) +8f(t_0+h) -f(t_0+2h) }{12h} + \mathcal{O}(h^4). \]Portanto, essa fórmula costuma ser uma excelente escolha quando a função é suave e pode ser avaliada com boa precisão.
5. Como escolher o valor de \(h\)
Em aritmética de precisão dupla, uma escolha inicial razoável para a diferença central é
\[ h \approx \varepsilon^{1/3} \max\left(1,\lvert t_0\rvert\right), \]onde \(\varepsilon\) é a precisão de máquina. Para números em precisão dupla,
\[ \varepsilon \approx 2{,}22 \times 10^{-16}. \]Assim,
\[ \varepsilon^{1/3} \approx 6{,}0 \times 10^{-6}. \]Uma escolha inicial pode ser, portanto,
\[ h \approx 6{,}0 \times 10^{-6} \max\left(1,\lvert t_0\rvert\right). \]Esse valor não é universalmente ótimo. Uma estratégia mais confiável é calcular a derivada usando vários valores de \(h\), por exemplo:
- \(h\);
- \(h/2\);
- \(h/4\);
- \(h/8\).
Se os resultados começarem a ficar estáveis, os algarismos que permanecem iguais são uma indicação da precisão obtida.
6. Extrapolação de Richardson
Também é possível aumentar a precisão usando a extrapolação de Richardson.
Considere a diferença central
\[ D(h) = \frac{f(t_0+h)-f(t_0-h)}{2h}. \]Como o erro principal é proporcional a \(h^2\), temos
\[ D(h) = f'(t_0)+Ch^2+\mathcal{O}(h^4), \]em que \(C\) é uma constante. Calculando também \(D(h/2)\), podemos eliminar o termo proporcional a \(h^2\):
\[ D_{\text{Richardson}} = \frac{4D(h/2)-D(h)}{3}. \]O erro da nova aproximação passa a ser da ordem de \(h^4\):
\[ D_{\text{Richardson}} = f'(t_0)+\mathcal{O}(h^4). \]Esse procedimento pode ser repetido para construir uma tabela de extrapolação e alcançar uma precisão ainda maior.
7. Método da diferença complexa
Se a função puder ser avaliada para argumentos complexos, existe uma técnica especialmente eficiente chamada método da diferença complexa.
Nesse método, usamos
\[ f'(t_0) \approx \frac{ \operatorname{Im}\left(f(t_0+ih)\right) }{h}, \]onde \(i\) é a unidade imaginária, definida por
\[ i^2=-1. \]Pela expansão de Taylor,
\[ f(t_0+ih) = f(t_0) +ihf'(t_0) -\frac{h^2}{2}f''(t_0) -\frac{ih^3}{6}f'''(t_0) +\cdots. \]Tomando somente a parte imaginária e dividindo por \(h\), obtemos
\[ \frac{ \operatorname{Im}\left(f(t_0+ih)\right) }{h} = f'(t_0)+\mathcal{O}(h^2). \]A principal vantagem é que essa fórmula evita a subtração de dois números reais muito próximos. Por isso, podemos usar valores de \(h\) extremamente pequenos, como
\[ h=10^{-20}. \]abs, comparações, max, min
ou definições por partes.
8. Exemplo numérico
Considere a função
\[ f(t)=\sin(t) \]e suponha que desejamos calcular a derivada em
\[ t_0=1. \]Sabemos analiticamente que
\[ f'(t)=\cos(t), \]portanto,
\[ f'(1)=\cos(1) \approx 0{,}540302305868. \]Usando a fórmula de cinco pontos com \(h=0{,}01\), obtemos
\[ f'(1) \approx \frac{ \sin(0{,}98) -8\sin(0{,}99) +8\sin(1{,}01) -\sin(1{,}02) }{0{,}12}. \]O resultado é muito próximo de
\[ 0{,}5403023059. \]Esse valor concorda com o resultado exato até várias casas decimais.
9. Implementação em Python
Diferença central
def derivada_central(f, t0, h):
return (f(t0 + h) - f(t0 - h)) / (2 * h)
Fórmula de cinco pontos
def derivada_5_pontos(f, t0, h):
return (
f(t0 - 2 * h)
- 8 * f(t0 - h)
+ 8 * f(t0 + h)
- f(t0 + 2 * h)
) / (12 * h)
Exemplo de utilização
import math
f = math.sin
t0 = 1.0
h = 1e-3
resultado = derivada_5_pontos(f, t0, h)
print("Derivada aproximada:", resultado)
print("Valor exato:", math.cos(t0))
10. Como testar vários valores de \(h\)
Uma maneira prática de procurar um valor adequado para \(h\) é calcular a derivada para vários valores e comparar os resultados:
import math
def derivada_5_pontos(f, t0, h):
return (
f(t0 - 2 * h)
- 8 * f(t0 - h)
+ 8 * f(t0 + h)
- f(t0 + 2 * h)
) / (12 * h)
f = math.sin
t0 = 1.0
for k in range(1, 14):
h = 10.0 ** (-k)
valor = derivada_5_pontos(f, t0, h)
print(
"h =",
h,
" | derivada aproximada =",
valor
)
Para valores grandes de \(h\), o erro de truncamento tende a ser dominante. Para valores muito pequenos, o erro de arredondamento tende a dominar. O melhor valor normalmente está entre esses dois regimes.
11. Quando a função contém ruído
Se os valores da função contiverem ruído, reduzir \(h\) pode piorar o resultado.
Suponha que os valores disponíveis sejam
\[ \widetilde{f}(t)=f(t)+\eta(t), \]onde \(\eta(t)\) representa o ruído. Como a derivada numérica divide uma diferença por \(h\), o ruído também pode ser ampliado por esse fator.
Nesse caso, uma alternativa é avaliar a função em vários pontos próximos de \(t_0\), ajustar um polinômio local e depois derivar esse polinômio.
Por exemplo, podemos ajustar
\[ p(t) = a_0 +a_1(t-t_0) +a_2(t-t_0)^2 +\cdots \]e usar
\[ f'(t_0)\approx p'(t_0)=a_1. \]Esse procedimento é conhecido como diferenciação por ajuste polinomial local. Em dados experimentais, ele costuma ser mais estável do que aplicar diretamente uma fórmula de diferenças finitas.
12. Recomendação final
Para uma função numérica comum, sem ruído, uma boa estratégia é:
- começar com a fórmula da diferença central;
- usar a fórmula de cinco pontos quando precisar de maior acurácia;
- testar vários valores de \(h\);
- observar em qual faixa os resultados se tornam estáveis;
- usar extrapolação de Richardson se precisar de mais precisão;
- usar a diferença complexa quando a função aceitar números complexos.
Em particular, uma excelente escolha geral é
\[ \boxed{ f'(t_0) \approx \frac{ f(t_0-2h) -8f(t_0-h) +8f(t_0+h) -f(t_0+2h) }{12h} } \]com \(h\) escolhido por meio de testes de estabilidade.
Nenhum comentário:
Postar um comentário