Anda di halaman 1dari 8

POLYNOMIAL INTERPOLATION USING NEWTON’S DIVIDED

DIFFERENCES

VIJAYA C RAMASAMI, KUID 698659

1. Problem Statement
Implement the polynomial interpolation using Netwon’s divided differences. Consider the
famous example:
1
(1) f (x) = −5≤x≤5
1 + x2
due to Carl Runge. Use two sets of nodes:
(2) Set I : xi = −5 + i ∗ h, i = 0, 1, · · · , n
 

(3) Set II : xi = −5 ∗ cos , i = 0, 1, · · · , n
n
10
(4) h=
n
The first set of notes are equidistant while the second set, often referred to as the Guass-Lobatto
Chebyshev points, are denser at both ends than the middle.
Denote by p(x) the interpolation polynomial which satisfies the conditions
(5) pn (xi ) = f (xi ), i = 0, 1, · · · , n
Let the maximum error be
 
xi + xi+1
(6) E(n) = max |pn − f |
i=0,1,··· ,n−1 2
Use your program to compute the error for various values of n, say n = 5, 10, 20, 40, and80 for
the two sets of nodes. What can you conclude based on the results you have obtained ?

2. Mathematical Formulation
2.1. Computation of Divided Differences. Divided Differences is an efficient numerical
method to compute the the Newton form of the interpolation polynomial. The Newton’s in-
terpolating polynomial has the following form:
n
X i=1
Y
(7) p(x) = di (x − xj )
i=0 j=0

We have to find the coefficients d0 , d1 , · · · , dn based on the n interpolation conditions, p(xi ) =


f (xi ), i = 0, 1, · · · , n. The divided difference technique is usually implemented by constructing a
divided difference table to compute the coefficients d0 , · · · , dn . Even though the divided difference
table is very handy for solving by hand, computer implementation of the table requires more
storage space than necessary. The pseudocode for another algorithm that is more effficient in
terms of lesser memory requirements is given below:

Date: 11/7/2002.
1
2 VIJAYA C RAMASAMI, KUID 698659

for i = 0 to n do
d[i] := f(x[i])
end do
for i = 1 to n do
for j = n to j step -1 do
d[i] := (d[i] - d[i-1])/x[i] - x[i-j])
end do
end do

In the above pseudocode, we first initialize d0 , · · · , dn to f (xi ), · · · f (xn ) respectively. We


already have d0 = f [x0 ]. The rest of the divided difference coefficients are computed one column
at a time and store the computed divided differences in d1 , d2 , · · · , dn , making sure that we do
not alter the divided difference values that are already computed.
We implemented the above algorithm in the C programming language. The C subroutine for
the computating the divided differences is given below:

void ComputeDividedDifferences(double (*f)(double), double *d, double *x,


int n)
{
int i, j;
/* Initialize d */
for(i = 0; i <= n; i++) d[i] = f(x[i]);

/* Compute Divided Differences */


for(i = 1; i <= n; i++)
for(j = n; j >= i; j--)
d[j] = (d[j] - d[j-1])/(x[j] - x[j-i]);
}

2.2. Evaluation of the Polynomial. Once the divided differences are computed, we can eval-
uate the above polynomial at an arbitraty point t using equation (7). A numerically stable and
computationally efficient method of implementing the Newton form is the Horner’s Algorithm
or Nested Multiplication. The following pseudocode computes u = pn (t) for a given value of t:

u := d[n]
for i = n-1 to 0 step -1 do
u := (t - x[i])u + d[i]
end do

We implemented the Horner’s algorithm in the C programming language. The C subroutine


for evaluating the polynomial is given below:

void Evaluate(double *d, double *x, int n, double *t, double *p, int nt)
{
int i, j;
for(i = 0; i <= nt; i++)
{
p[i] = d[n];
for(j = n-1; j >= 0; j--)
p[i] = d[j] + (t[i] - x[j])*p[i];
}
POLYNOMIAL INTERPOLATION USING NEWTON’S DIVIDED DIFFERENCES 3

2.3. Spacing between Nodes. The spacing between nodes is an important parameter in poly-
nomial interpolation. It can be easily shown that the interpolation error increases without bounds
for increase values of n in the case of equidistant nodes. For example, the interpolation error in
the Runge’s polynomial using equidistant nodes in the range [−5, 5] can be approximated as:
 n+1 r !
20(n + 1) 2π
(8) max |f (x) − pn (x)| ∼
x∈[−5,5] ne n+1

1 1
Equidistant
Nodes Chebyshev
0.9 0.9 Nodes

0.8 0.8

0.7 0.7

0.6 0.6
f(xi) −>

f(xi) −>

0.5 0.5

0.4 0.4

0.3 0.3

0.2 0.2

0.1 0.1

0 0
−5 0 5 −5 0 5
xi −> xi −>

Figure 1. Equidistant and Chebyshev Nodes

It can be seen from the above equation that the interpolation error increases as (20/e)n+1
as n → ∞. A method to avoid this increase in interpolation error is to use non-equdistant
nodes. We can show for the case of the Runge function that if we use closely spaced points at
the two ends of the specified interval, we can achieve a very good fit for higher values of n. In
this project, we prove using numerical experiments that the Gauss-Lobatto-Chebyshev points
are a better choice of nodes than equidistant points for interpolating the Runge’s function using
polynomials.
2.4. Interpolation Error. The Interpolation error is usually measured using the L∞ -norm (or
maximum in a given interval). One method to obtain an estimate of the interpolation error is to
compute the error between the function and its polynomial approximation at midpoints between
adjacent nodes. Thus the interpolation error can be computed using:
 
xi + xi+1
(9) E(n) = max |pn − f |
i=0,1,··· ,n−1 2
The C-subroutine that performs this error estimation is given below:

double ComputeMaxError(double (*f)(double), double *d, double *x, int n)


{
double e = 0, temp, t, p;
4 VIJAYA C RAMASAMI, KUID 698659

int i;
for(i = 0; i < n; i++)
{
t = (x[i] + x[i+1])/2;
Evaluate(d, x, n, &t, &p, 0);
temp = fabs(f(t) - p);
if (temp > e) e = temp;
}
return e;
}

3. Numerical Experiments
3.1. Comparision. We performed experiments with the divided difference technique and the
two types of nodes specified in the previous section for small/moderate values of n. The plots
in figure (2) clearly illustrate that the Chebyshev nodes achieve a better fit than the equidistant
nodes. In fact, interpolation using equidistant nodes shows a significant oscillatory behaviour
for large values of n, especially on the corner nodes. The interpolation error caused due to this
oscillatory behaviour increases without bound as n increase, as expected from theory.

Equidistant Nodes Chebyshev Nodes


1 0.9
f(x ) f(x )
i i
p (x) p (x)
n n
0.8

0.5
0.7

0.6

0
0.5

0.4
−0.5

0.3

0.2
−1

0.1

−1.5 0
−5 0 5 −5 0 5

Figure 2. Interpolation using Equidistant and Chebyshev Nodes - Graphical Comparision

3.2. Error Performance. The interpolation error for the netwon form of the interpolation
polynomial for the given choice of nodes for various values of n were computed and plotted in
figure (3). We used log10 (E) to cover the wide dynamic ranges of the error. It can be seen that
the Chebyshev Nodes provide increasingly good approximations for increasing values of n, while
the interpolation error of the Netwon polynomial increases without bound for increasing values
of n.
We assume linear convergence for interpolation using Chebyshev Nodes and plotted the con-
vergence graph in figure (3). It can be seen that:
|En+1 |
(10) ≤ 1.4
|En |
POLYNOMIAL INTERPOLATION USING NEWTON’S DIVIDED DIFFERENCES 5

Error Performance Convergence Rate using Chebyshev Nodes


5 0 15

4 Equidistant −0.5
Nodes

3 −1

log10(E) (Chebyshev Nodes)


log10(E) (Equidistant Nodes)

10

2 −1.5

1 Chebyshev −2 En+1/En
Nodes

5
0 −2.5

≈ 1.4

−1 −3

−2 −3.5 0
0 10 20 30 40 0 10 20 30 40
n −−> n −−>

Figure 3. Error Performance of Divided Differences Interpolation and the Con-


vergence Graph for Interpolation using Chebyshev Nodes.

Double Precision Computations Single Precision Computations


1 3

0.9
2.5

0.8
2
Interpolation
0.7 Polynomial
Error due to limited
Nodes
1.5 precision computations
0.6

0.5 1

0.4
0.5

0.3
0
0.2

−0.5
0.1

0 −1
−5 0 5 −5 0 5

Figure 4. Effect of Finite Machine Precision on Interpolation (with Chebyshev Nodes)

3.3. Limitations due to Machine Precision. Even though the interpolation error using
Chebyshev nodes theoritically decreases with increasing values of n, limitations due to finite
machine precision will result in large errors for large values of n. This fact can be easily proven
by executing the algorithm in different levels of machine precision and analyzing the error per-
formance. In the C programming language, we used float for single precision computations and
double for double precision computations and the result for n = 30 is shown in figure (4). It can
be clearly seen that large errors occur for values of n close to 5. We performed futher analysis
and found that the errors (oscillations) are mostly caused in the nested multiplication routine.
6 VIJAYA C RAMASAMI, KUID 698659

The error (oscillations) are negligible at the output of the divided differences computation rou-
tine even for large values of n. For double precision computations, this error behavior starts
approximately around n = 45.

n Error (Equidistant Nodes) Error (Chebyshev Nodes)


5 0.1212 0.0592
10 1.5317 0.1310
20 3.4025 0.0140
40 2287.7 3.3987 × 10−4
80 4.6734 × 109 2.1471 × 105
Table 1. Table of Errors for Interpolation using Equidistant and Chebyshev
nodes for various values of n

4. Conclusions
The Divided Differences Algorithm was implemented using the C programming language to
compute the Newton form of the interpolating polynomial for the given function using equidis-
tant and chebyshev nodes. The following results were observed as a result of the Numerical
experiments:
• Interpolation using Chebyshev nodes always achieves a better fit than interpolation using
equidistant nodes.
• The interpolation error using equidistant nodes increases without bounds a the number
of nodes are increased, as expected from theory.
• The interpolation error using Chebyshev nodes converges linearly with the convergence
constant ≈ 1.4.
• Under finite machine precision, even the use of Chebyshev nodes will cause large errors.

5. Source Code Listing


5.1. library.cc.
#include "library.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"

/* Divided Differences Computation */


void ComputeDividedDifferences(double (*f)(double), double *d, double *x,
int n)
{
int i, j;
/* Initialize d */
for(i = 0; i <= n; i++) d[i] = f(x[i]);

/* Compute Divided Differences */


for(i = 1; i <= n; i++)
for(j = n; j >= i; j--)
d[j] = (d[j] - d[j-1])/(x[j] - x[j-i]);
}

/* Polynomial Evaluation - Horner’s Algorithm */


void Evaluate(double *d, double *x, int n, double *t, double *p, int nt)
{
POLYNOMIAL INTERPOLATION USING NEWTON’S DIVIDED DIFFERENCES 7

int i, j;
for(i = 0; i <= nt; i++)
{
p[i] = d[n];
for(j = n-1; j >= 0; j--)
p[i] = d[j] + (t[i] - x[j])*p[i];
}
}

/* The Runge Function */


double f(double x)
{
return 1/(1+pow(x,2));
}

/* Error Computation */
double ComputeMaxError(double (*f)(double), double *d, double *x, int n)
{
double e = 0, temp, t, p;
int i;
for(i = 0; i < n; i++)
{
t = (x[i] + x[i+1])/2;
Evaluate(d, x, n, &t, &p, 0);
temp = fabs(f(t) - p);
if (temp > e) e = temp;
}
return e;
}

5.2. main.cc.
#include <stdio.h>
#include <math.h>
#include "library.h"
#include <stdlib.h>

#define PI 3.141592

void main(void)
{
int n = 30, i, nt = 1000;
double h, *d, *x, *t, *p, ht,e;
FILE *fp1, *fp2;

/* Allocate Memory for Operations */


d = (double *)calloc(n+1, sizeof(double));
x = (double *)calloc(n+1, sizeof(double));
p = (double *)calloc(nt+1, sizeof(double));
t = (double *)calloc(nt+1, sizeof(double));

/* Error Checking */
if ((d == NULL) || (x == NULL) || (p == NULL) || (t == NULL))
{
8 VIJAYA C RAMASAMI, KUID 698659

printf("Memory Allocation Failure... Aborting...");


exit(-1);
}

/* File to Save the results and for Plotting */


fp1 = fopen("interp_polydata.dat", "wt");
fp2 = fopen("interp_nodes.dat", "wt");

if ((fp1 == NULL)||(fp2 == NULL))


{
printf("Cannot open output file... Aborting...");
exit(-1);
}

/* Generate the Nodes */


h = 10.0/n;
for(i = 0; i <= n ; i++)
{
/* x[i] = -5 + i*h; */
x[i] = -5*cos(i*PI/n);
d[i] = 1/(1+pow(x[i],2));
}

/* Compute Divided Differences */


ComputeDividedDifferences(f, d, x, n);

/* Evaluate the Polynomial */


ht = 10.0/nt;
for(i = 0; i <= nt ; i++) t[i] = -5 + i*ht;
Evaluate(d, x, n, t, p, nt);

/* Save the Values */


for(i = 0; i <= nt ; i++) fprintf(fp1, "%.4f\t%.4f\n", t[i], p[i]);
for(i = 0; i <= n ; i++) fprintf(fp2, "%.4f\t%.4f\n", x[i], f(x[i]));

/* Compute Error */
e = ComputeMaxError(f, d, x, n);
printf("e = %lf\n", e);

/* Clean Up */
fclose(fp2);
fclose(fp1);
free(d);
free(t);
free(p);
free(x);
}

Anda mungkin juga menyukai