Aproximación de derivadas
Podemos aproximar la derivada de una función utilizando el método denominado Diferencias Finitas. Este método se puede obtener utilizando una expansión en Series de Taylor de una función \(f\) respecto a un punto cercano. Considerando una discretización de \(N\) puntos sobre la variable \(x\in[x_{\text{min}}, x_{\text{max}}]\), definimos
Ahora, definiremos \(f_i\) como la aproximación de la función \(f\) en el punto \(x=x_i\), es decir, \(f_i = f(x_i)\).
Podemos aproximar la derivada de la función \(f\) en el punto \(x_i\), o sea \(f'_i=f'(x_i)\), de las siguientes \(3\) maneras:
- Diferencia finita adelantada
- Diferencia finita atrasada
- Diferencia finita central
Realice un programa que solicite:
- El dominio de \(x\), es decir, \(x_{\text{min}}\) y \(x_{\text{max}}\).
- La cantidad de puntos de discretización \(N\).
- El tipo de aproximación, o sea, si es adelantada, atrasada o central.
Y calcule la derivada de la función. El programa debe mostrar el error entre la derivada real y su aproximación. Para esto utilizaremos la norma \(L-2\) o distancia euclideana de la siguiente forma:
donde \(inicio\) y \(fin\) dependerá de el tipo de aproximación que esté utilizando.
La función de prueba que utilizaremos será: \(f(x) = x \sin (x)\).
Ejemplos
x min: 0
x max: 5
N: 32
Tipo: atrasada
Error: 1.1242595459725062
x min: 0
x max: 5
N: 32
Tipo: central
Error: 0.07297275585321655
x min: 0
x max: 5
N: 64
Tipo: adelantada
Error: 0.7766862915195681
x min: 0
x max: 5
N: 64
Tipo: central
Error: 0.025254054492286914
Solución
from math import sin, cos
# Funcion a derivar
def f(x):
return x * sin(x)
# Derivada de la funcion
def fp(x):
return sin(x) + x * cos(x)
# Evaluar la funcion en una lista de valores
def evaluar_f(x):
fx = list()
for i in range(len(x)):
fx.append(f(x[i]))
return fx
# Evaluar la derivada en una lista de valores
def evaluar_fp(x):
fpx = list()
for i in range(len(x)):
fpx.append(fp(x[i]))
return fpx
# Cacular Diferencias finitas
def diferencias_finitas(x, dx, tipo):
fd = list()
N = len(x)
fe = evaluar_f(x)
# Calcular según el tipo de diferencias finitas
if tipo == "adelantada":
for i in range(N-1):
fw = (fe[i+1] - fe[i]) / dx
fd.append(fw)
elif tipo == "atrasada":
for i in range(1, N):
bw = (fe[i] - fe[i-1]) / dx
fd.append(bw)
elif tipo == "central":
for i in range(1, N-1):
cd = (fe[i+1] - fe[i-1]) / (2 * dx)
fd.append(cd)
return fd
# Calcular el error
def error(real, approx):
err = 0
for i in range(len(approx)):
err += (real[i] - approx[i]) ** 2
return err ** 0.5
# Solicitar datos
x_min = float(input("x min: "))
x_max = float(input("x max: "))
N = int(input("N: "))
tipo = input("Tipo: ")
# Crear lista de valores de x
x = list()
dx = (x_max - x_min) / (N - 1)
for i in range(N):
x.append(x_min + i * dx)
# Calcular diferencias finitas y derivada exacta
fd = diferencias_finitas(x, dx, tipo)
fpe = evaluar_fp(x)
# Obtener valores de inicio y fin para el error
# Considerar que el error se calcula en los puntos interiores según el tipo de diferencias finitas
if tipo == "adelantada":
i = 0
f = N - 1
elif tipo == "atrasada":
i = 1
f = N
elif tipo == "central":
i = 1
f = N - 1
# Calcular error
error = error(fpe[i:f], fd)
print("Error:", error)