Issue
I write a program to get derivative. InterpolatedUnivariateSpline is used for calculating f(x+h). The red line is derivative of cosine, the green line is cosine consine, the blue line is -sine function. The red and blue line are matched. It works well in the following.
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()
But I encounter some problem. In my project, my variable x(frequency) vary from 10^7 to 2.2812375*10^9, its step is 22487500,so I change array x. As a result, I get the following result.
The derivative is a line and almost close to 0, It is not -sine function. How do I solve this?
Solution
You have a loss of significance problem. It means that when adding a large floating point number to a small one, the precision of the small one is partially lost as a numpy double can only hold 64 bits of information.
To solve this issue you have to make sure that the scale of the numbers you add/multiply/divide is not too different. One simple solution is dividing x
by 1e9
or multiplying h
by 1e9
. If you do this you get essentially the same precision as in your example.
Also if x
has high enough resolution a simpler way to numerically differentiate the function would be der = np.diff(y) / np.diff(x)
. This way you do not have to worry about setting h. However in this case note that dy
is one element shorter that y
, and dy[i]
is actually an approximation of the derivative at `(x[i] + x[i+1]) / 2. So to plot it you would do:
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')
Answered By - Martin Stancsics
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.