13.2.4 Approximating derivatives of discrete functions
The numdiff command finds
numerical approximations to derivatives.
-
numdiff takes three mandatory arguments and one
optional argument.
-
X=[α0,α1,…,αn],
Y=[β0,β1,…,βn], two lists of real numbers,
where n≥ 1.
- x0, a real number.
- Optionally, m, an integer or a sequence of integers (by default 1).
Note that X, Y and x0 can also be symbolic expressions.
- numdiff(X,Y,x0 ⟨,m⟩)
returns an approximation of the mth derivative of a function f
at x0, or a sequence of derivatives of order given by the
sequence m, where f has values given by f(αk)=βk,
k=0,1,…,n.
- numdiff uses Fornberg’s algorithm with complexity O(n2m) in
both time and space.
- Note that α0,α1,…,αn do not have to be equally
spaced, but they must be mutually different and input in ascending
order. There are no restrictions on the choice of x0.
- The algorithm performs reasonably fast on inexact input data, with rounding errors
usually not damaging for m≤ 4. For higher m, consider
providing input data in an exact form. This will make the algorithm run
considerably slower, but will also avoid numerical instabilities due to the
unlimited precision arithmetic being used.
In case you need only the first or second derivative at a sequence of points,
you can use the interp command (see Section 17.1.2) which
uses cubic spline interpolation. Note that this method does not accept symbolic
input.
Examples
Let f(x)=sin(x) e−x, x∈[0,1]. Sample this function
at the points in
X=[0,0.1,0.2,0.4,0.5,0.7,0.8,1]
|
to approximate f′′(1/π).
f:=unapply(sin(x)*exp(-x),x):;
X:=[0,0.1,0.2,0.4,0.5,0.7,0.8,1]:;
Y:=apply(f,X):; |
Now you can approximate the second derivative of f at the point
x0=1/π.
x0:=1/pi:;
d:=numdiff(X,Y,x0,2) |
Finally, compute the relative error of the obtained approximation.
abs(d-f''(x0))/abs(f''(x0))*100 |
The result is expressed in percentages.
Use a sequence of values for the parameter m to find a list of
approximations of the respective derivatives at x0. This is faster
than calling numdiff to approximate one derivative at a time.
For example, approximate the first, second and third derivative of
the function
at the point x0=0.57 by sampling f at 21 equidistant points in
the segment [0,1].
f:=unapply(1-1/(1+x^2),x):;
X:=[(0.05*k)$(k=0..20)]:;
Y:=apply(f,X):;
numdiff(X,Y,0.57,1,2,3) |
|
| ⎡
⎣ | 0.649439427528,0.0217571104587,−2.99724196738 | ⎤
⎦ |
| | | | | | | | | | |
|
Actually, f′(x0)=0.649439427528,
f′′(x0)=0.0217571104558 and f′′′(x0)=−2.99724196764.
numdiff can be used for generating custom finite-difference
stencils for approximation of derivatives.
For example, let X=[−1,0,2,4], Y=[a,b,c,d] and x0=1. To obtain an
approximation formula for the second derivative:
numdiff([-1,0,2,4],[a,b,c,d],1,2) |
The approximation is always a linear combination of elements in Y,
regardless of X, x0 and m.
Given the lists
X=[α0,α1,…,αn] and Y=[β0,β1,…,βn],
the Lagrange polynomial passing through points
(αk,βk) where k=0,1,…,n can be obtained by setting
m=0 and entering a symbol for x0.
Let X=[−2,0,1] and Y=[2,4,1]:
expand(numdiff([-2,0,1],[2,4,1],x,0)) |
Note that by entering
lagrange([-2,0,1],[2,4,1],x) |
we obtain the same result.