Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Introdução a Classes utilizando Python.

0 votos
13 visitas
perguntada Out 7 em Economia por CICERO FILHO (26 pontos)  
editado Out 7 por CICERO FILHO

Examine o Código abaixo para calcular uma aproximação de diferença para trás com a derivada de uma função f(x):

from math import *

class Backward(object):
       def __init__(self, f, h=e-9):
              self.f, self.h = f, h
       def __call__(self, x):
              h, f = self.h, self.f
              return (f(x) - f(x-h))/h # finite difference

dsin = Backward(sin)
e = dsin(0) - cos(0); print ’error:’, e
dexp = Backward(exp, h=e-7)
e = dexp(0) - exp(0); print ’error:’, e

Os outputs apresentam:

error: -1.00023355634 
error: 371.570909212

Pergunta: Será que a aproximação é tão ruim assim ou será que existe algum bug no Código?

Nome do arquivo: find_errors_class

Referência: Exercício 7.17 - Cap 7 – do livro “A Primer on Scientific Programming with Python"- 5ed - pag. 477 - Hans Petter Langtangen.

Compartilhe

1 Resposta

0 votos
respondida Out 7 por CICERO FILHO (26 pontos)  

As regras básicas de cálculo definem derivada como:

\[\frac{df}{dx}=\lim_{h\rightarrow0}{\frac{f\left(x+h\right)-f(x)}{h}}\]

A derivada de uma função é a diferença entre seus valores quando x é extremamente baixo.

É trivial derivar as seguintes formulas:

\[\frac{d}{dx}(sen(x))=\cos(x)\]

\[\frac{d}{dx}(\exp(x))=\exp(x)\]

Assim, ambos deveriam ser iguais em algum “x” em particular. Isso é o que a questão está pedindo para se verificar.

Resolução do Problema:

O código da amostra fornecida indica que \(dsin\) e \(dexp\) são as derivados do \(sen(x)\) e \(exp(x)\) calculadas usando a definição. Então, \(dsin\) e \(dexp\) deveriam ser iguais a \(sen(x)\) e \(exp(x)\) . Porém, quando o código verifica isso, ele obtém o seguinte resultado:

error:\ -1,00023355634
error:\ \ 371,570909212

Isso indica que \(dsin\) e \(cos(x)\) são diferentes e que a diferença entre eles é -1,00023355634... que é um valor extremamente elevado considerando que os valores do seno variam entre -1 e 1. O mesmo para \(dexp\) e \(exp(x)\).

Assim, para verificar cuidadosamente o código, percebe-se que o problema está na configuração:

\[h=e^{-9}\]

O Python retorna o valor de \(e^{-9}\) como -6,281718171540955.

O \(h\) deveria estar o mais próximo possível de 0.

Então, para definir uma referência, supõe-se que a derivada de qualquer grau significativo, o \(h\) deve ser inferior a \({10}^{-3}\). Então é possível verificar que \(e^{-9}\) é um número muito grande neste contexto. Esse é o problema com o Código.

Por outro lado, o Python retorna o valor de \({1e}^{-9}\), i.e. \({1e}^{-9}=\ {10}^{-8}\) que é menor do que o exigido.

Assim, o Python interpreta \(e^{-9}\) como o número \(e (= 2.718...)\) retirando o número o número 9. Porém interpreta \({1e}^{-9}\) como o número 1 exponencial de -9.

Assim, basta adicionar 1 antes de \(e^{-9}\) e o Código fica correto.

No código, uma classe chamada Backward é criada com duas variáveis \(f\) e \(h\). O método será executado. Os objetos \(dsin\) e \(dexp\) são criados e o método é executado corretamente.

Assim, o código é verificado e o bug é detectado.

Início do calculo computacional:

from math import *

class Backward:      

    def __init__(self,f,h=1e-9):  #Inicializando f e h
    self.f,self.h = f,h

#Método que computa a a derivada usando Backward difference

def __call__(self,x):           
    h,f = self.h,self.f
    return ((f(x)-f(x-h))/h)

dsin = Backward(sin)        #criando objeto da classe Backward com função seno 
error = dsin(0) - cos(0)    #Calculando o erro de dsin com a derivada atual
print("error: ", error)     # printando o resultado

dexp = Backward(exp, h = 1e-7)  #criando objeto da classe Backward com função exp 
error2 = dexp(0) - exp(0)       #Calculando o erro de dexp com a derivada atual
print("error:",error2)          #printando o resultado

error:  0.0
error: -5.048639195592841e-08
...