Previous Up Next

5.19.7  Numerical differentiation : numdiff

numdiff takes three mandatory arguments: lists X={α01,…,αn}, Y={β01,…,βn} of real numbers, where n≥ 1, and a real number x0. The optional fourth argument is an integer m, which defaults to 1. The function returns an approximation of the m-th derivative of function f, given by fk)=βk, k=0,1,…,n, at point x0.

The strategy is to use Fornberg’s algorithm described in “Generation of Finite Difference Formulas on Arbitrarily Spaced Grids”, Mathematics of Computation, 51(184):699–706, 1988. The complexity of this algorithm is O(n2m) in both time and space. To avoid numerical instability, numdiff operates in exact arithmetic. Unless a symbolic variable is present in the input, the result is returned using the floating-point representation.

Note that α01,…,α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.

For example, let f(x)=sin(x)ex, x∈[0,1]. We sample this function at points

X=[0,0.1,0.2,0.4,0.5,0.7,0.8,1] 

by computing the list Y=f(X). Input :

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 we approximate the second derivative at the point x0=1/π. Input :

x0:=1/pi:; d:=numdiff(X,Y,x0,2)

Finally, we compute the relative error of the obtained approximation. Input :

abs(d-f’’(x0))/abs(f’’(x0))*100

Output :

2.82983388966e-05

The result is expressed in percentages.

Optionally, a sequence of values of the parameter m may be passed to numdiff. In that case the function returns the list of approximations of the respective derivatives at x0. This is faster than calling numdiff to approximate one derivative at a time. For example, let us approximate the zeroth, first and second derivative of the function

f(x)=1−
1
1+x2
,   x∈[0,1], 

at point x0=γ, where γ≈ 0.57722 is Euler-Mascheroni constant, by sampling f at 21 equidistant points in the segment [0,1]. Input :

f:=unapply(1-1/(1+x^2),x)
X:=[(0.05*k)$(k=0..20)]:; Y:=apply(f,X):;
numdiff(X,Y,euler_gamma,0,1,2)

Output :

[0.249912571952,0.649519026355,0.000393517939481]

The correct values are f(γ)=0.249912571952, f′(γ)=0.649519026356 and f″(γ)=0.000393517946748.

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, input :

numdiff([-1,0,2,4],[a,b,c,d],1,2)

Output :

2*a/5-b/2+d/10

The approximation is always a linear combination of elements in Y, regardless of X, x0 and m.

Given X and Y, the Lagrange polynomial passing through points (αkk) where k=0,1,…,n can be obtained by setting m=0 and entering a symbol for x0. For example, letting X=[−2,0,1] and Y=[2,4,1] input :

expand(numdiff([-2,0,1],[2,4,1],x,0))

Output :

-4*x^2/3-5*x/3+4

The same result is obtained by entering lagrange([-2,0,1],[2,4,1],x).


Previous Up Next