quarta-feira, 4 de novembro de 2026

Calculando numericamente a derivada de uma função

Como calcular numericamente a derivada de uma função

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.

Observação: embora a fórmula de cinco pontos seja mais precisa teoricamente, escolher um valor de \(h\) muito pequeno ainda pode aumentar os erros de arredondamento.

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}. \]
Atenção: o método da diferença complexa só funciona se a implementação da função aceitar números complexos. Ele pode não funcionar corretamente para funções que usam operações como 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 é:

  1. começar com a fórmula da diferença central;
  2. usar a fórmula de cinco pontos quando precisar de maior acurácia;
  3. testar vários valores de \(h\);
  4. observar em qual faixa os resultados se tornam estáveis;
  5. usar extrapolação de Richardson se precisar de mais precisão;
  6. 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