我写了一个程序来获得衍生物。 InterpolatedUnivariateSpline用于计算f(x + h)。红线是余弦的导数,绿线是余弦consine,蓝线是-sine函数。红色和蓝色线匹配。它在以下情况下运作良好。
from scipy.interpolate import InterpolatedUnivariateSpline
import numpy as np
import matplotlib.pyplot as plt
pi = np.pi
x = np.arange(0,5*pi,0.2*pi)
y = np.cos(x)
f2 = InterpolatedUnivariateSpline(x, y)
#Get dervative
der = []
for i in range(len(y)):
h = 1e-4
der.append( ( f2(x[i]+h)-f2(x[i]-h) )/(2*h) )
der = np.array(der)
plt.plot(x, der, 'r', x, y, 'g', x, -np.sin(x),'b')
plt.show()
但是我遇到了一些问题。在我的项目中,我的变量x(频率)从10 ^ 7变化到2.2812375 * 10 ^ 9,其步长为22487500,所以我改变了数组x。 结果,我得到以下结果。
导数是一条直线,几乎接近于0,它不是-sine函数。我该如何解决这个问题?
答案 0 :(得分:1)
您遇到loss of significance问题。这意味着当向一个小浮点数添加一个大的浮点数时,小的浮点数的精度会部分丢失,因为numpy double只能容纳64位信息。
要解决此问题,您必须确保添加/乘/除的数字的比例不会太大。一个简单的解决方案是将x
除以1e9
或将h
乘以1e9
。如果这样做,您将获得与示例中相同的精度。
此外,如果x
具有足够高的分辨率,则在数字上区分函数的简单方法是der = np.diff(y) / np.diff(x)
。这样您就不必担心设置h了。但是在这种情况下请注意dy
是y
的一个元素,dy[i]
实际上是`(x [i] + x [i + 1])的导数的近似值/ 2.所以要绘制它你会做:
der = np.diff(y) / np.diff(x)
x2 = (x[:-1] + x[1:]) / 2
plt.plot(x2, der, 'r', x, y, 'g', x, -np.sin(x),'b')