Newton interpolation
Build the divided-difference table and evaluate the Newton polynomial efficiently with nested multiplication.
Core idea: divided differencesNumerical methods tutorial
A practical guide to Newton interpolation, Lagrange interpolation, barycentric interpolation, cubic splines, Chebyshev nodes, the Runge phenomenon, plots, errors, and reusable Python code.
This page is written for anyone who wants to understand how to interpolate data points in Python, not just copy a formula.
Build the divided-difference table and evaluate the Newton polynomial efficiently with nested multiplication.
Core idea: divided differencesUnderstand the direct polynomial formula and how SciPy can create the Lagrange polynomial for small educational examples.
Core idea: polynomial basis functionsCompare equispaced nodes against Chebyshev nodes and see why node choice matters for the Runge phenomenon.
Core idea: better node placementCompare a numerically stable polynomial interpolation method used by SciPy for practical evaluation.
Core idea: stable polynomial evaluationSee why piecewise cubic interpolation can avoid many high-degree polynomial oscillations.
Core idea: smooth piecewise interpolationNode placement can matter as much as the interpolation formula. With high-degree polynomial interpolation, equally spaced points may create large oscillations near the interval edges. Chebyshev nodes cluster near the endpoints and often reduce that behavior.
Easy to understand and common in first examples, but they can produce large edge oscillations for functions such as Runge's function when the polynomial degree grows.
x_nodes = np.linspace(-1, 1, n)
Nodes are denser near the interval endpoints. For global polynomial interpolation, this usually gives a much better error profile than equally spaced nodes.
k = np.arange(1, n + 1)
x_nodes = np.cos((2*k - 1) * np.pi / (2*n))
| Node type | What tends to happen | Try it in the demo |
|---|---|---|
| Equispaced | Simple spacing, but more vulnerable to Runge oscillations. | Use Runge function with 11 or 21 nodes. |
| Chebyshev | Lower edge oscillation for many global polynomial examples. | Switch the node type to Chebyshev and compare the curve. |
Newton interpolation writes the polynomial using coefficients from a divided-difference table. It is useful because adding one new data point does not require rebuilding the whole polynomial from scratch.
Start with data points (x0, y0), (x1, y1), .... The
x-values must be unique.
The first column is y. Every next column divides the
difference of previous values by the distance between x-nodes.
Use nested multiplication for a stable and compact evaluation of the polynomial.
import numpy as np
from polynomial_interpolation import (
evaluate_newton_polynomial,
newton_coefficients,
)
x_nodes = np.array([-1.0, -0.5, 0.0, 0.5, 1.0])
y_nodes = 1 / (1 + 25 * x_nodes**2)
coefficients = newton_coefficients(x_nodes, y_nodes)
value = evaluate_newton_polynomial(coefficients, x_nodes, 0.25)
print(float(value))
Lagrange interpolation builds the same polynomial as Newton when the same nodes are used. The formula is direct and easy to read, so it is common in numerical methods courses.
import numpy as np
from scipy.interpolate import lagrange
x_nodes = np.array([-1.0, -0.5, 0.0, 0.5, 1.0])
y_nodes = 1 / (1 + 25 * x_nodes**2)
polynomial = lagrange(x_nodes, y_nodes)
print(polynomial(0.25))
| Method | Best for learning | Práctical note |
|---|---|---|
| Newton | Divided differences, incremental interpolation | Good method to implement from scratch. |
| Lagrange | Understanding the interpolation polynomial formula | Clear mathematically, but less efficient for updates. |
| Barycentric | Stable polynomial interpolation | Usually preferred for numerical polynomial evaluation. |
| Cubic spline | Smooth interpolation without high-degree oscillation | Often more robust for real data. |
The repository keeps the Newton method as small, readable NumPy functions. Here are the core pieces, straight from polynomial_interpolation.py.
The table starts with the y values in the first column.
Each next column divides the difference of the previous column by the
distance between the matching x-nodes. The Newton coefficients are
simply the top row of the finished table.
def divided_difference_table(x, y):
n = len(x)
table = np.zeros((n, n))
table[:, 0] = y
for order in range(1, n):
for row in range(n - order):
numerator = table[row + 1, order - 1] - table[row, order - 1]
denominator = x[row + order] - x[row]
table[row, order] = numerator / denominator
return table
# Newton coefficients are the top row of the table:
coefficients = divided_difference_table(x, y)[0, :]
Instead of expanding the polynomial, the evaluator walks the coefficients backwards and multiplies as it goes. This is numerically stable, works on a single point or a whole NumPy array, and keeps the cost linear in the number of nodes.
def evaluate_newton_polynomial(coefficients, x_nodes, x_eval):
result = np.full_like(x_eval, coefficients[-1], dtype=float)
for i in range(len(coefficients) - 2, -1, -1):
result = result * (x_eval - x_nodes[i]) + coefficients[i]
return result
The benchmark builds the Newton polynomial from this repository and the Lagrange, barycentric and cubic-spline interpolants from SciPy, then measures the maximum and L2 error against the true function on a dense grid.
from scipy.interpolate import (
BarycentricInterpolator,
InterpolatedUnivariateSpline,
lagrange,
)
# Newton (implemented in this repository)
coefficients = newton_coefficients(x_nodes, y_nodes)
y_newton = evaluate_newton_polynomial(coefficients, x_nodes, x_grid)
# Lagrange, barycentric and cubic spline (SciPy)
y_lagrange = lagrange(x_nodes, y_nodes)(x_grid)
y_bary = BarycentricInterpolator(x_nodes, y_nodes)(x_grid)
y_spline = InterpolatedUnivariateSpline(x_nodes, y_nodes, k=3)(x_grid)
# Error against the true function on a dense grid
max_error = np.max(np.abs(y_newton - y_true))
l2_error = np.sqrt(np.trapezoid((y_newton - y_true)**2, x_grid))
Change the function, nodes, and evaluation point. The plot shows why Newton and Lagrange give the same polynomial for the same nodes, and why Chebyshev nodes often reduce oscillation.
This page is also useful for readers looking for Newton interpolation in Python, Lagrange interpolation in Python, and divided differences in Python.
The main repository script lets you compare equispaced nodes and Chebyshev nodes, compute maximum error, estimate L2 error, and save results to CSV.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python polynomial_interpolation.py
Support the project
I built this for people looking for a clear interpolation reference with code, plots, and explanations. If it helped you, a coffee helps me publish more numerical methods resources.