Lagrange interpolation and Newton's interpolation - MATLAB implementation
Lagrange interpolation and Newton's interpolation
Special paper of undergraduate experiment report
拉格朗日插值,牛顿差值,MATLAB
Experimental purpose and requirement
Experimental Purpose: The purpose of this experiment is to compare the accuracy and efficiency of Lagrange interpolation and Newton's interpolation methods for approximating a function based on a set of discrete data points. The two interpolation methods will be implemented and their results will be compared based on the error between the approximated values and the actual function values.
Experimental Requirements: To conduct this experiment, the following requirements must be fulfilled:
- Data Collection: A set of discrete data points will be collected to approximate a given function. Here we use data on the textbook and some randomised data.
- Lagrange Interpolation: The Lagrange interpolation method will be implemented using the collected data points. The implementation should be able to take in a set of data points and approximate the function at any given point.
- Newton's Interpolation: The Newton's interpolation method will also be implemented using the collected data points. The implementation should be able to take in a set of data points and approximate the function at any given point.
- Error Calculation: The error between the approximated values and the actual function values will be calculated using a suitable error metric such as the Mean Squared Error or Absolute Error.
- Comparison of Results: The results obtained from both the interpolation methods will be compared based on the error between the approximated values and the actual function values. The accuracy and efficiency of the two methods will be evaluated based on this comparison.
Experimental principle and main content
Equipment, Toolbox
Only Symbolic Math Toolbox is used here.
It can be done without using Symbolic Math Toolbox, yielding a numerical value at the end, but this is not implemented here. In this report, we first calculate the interpolated polynomial symbolically, then compute their numerical value.
Core formulae: Lagrange interpolation
The Lagrange interpolated polynomial is given by
where
Core formulae: Newton's interpolation
The main idea of Newton's interpolation is
which is the same as
And the dividend difference term is recursively calculate by
Before designed our code, we can do some simple calculation to check whether our thought is correct.
The recurrence relation \((5.14)\) was used to calculate the divided differences of the function
\[f(x)=10 \mathrm{e}^{-3 x}, \quad 0 \leqslant x \leqslant 2, \]tabulated on the point set \(\{1.60,1.63,1.70,1.76,1.80\}\). The results are shown in Tables 5.1 and 5.2. All data and all calculated numbers were rounded to a fixed precision before they were recorded and used for subsequent calculation. The difference between the tables is that in Table
By the data in table 5.2, we have that
By considering rounding,
clear;
% range_x = [-10, 10];
% sz_vec = [4, 1];
% rng(1);
% x_vec = randperm(range_x(2), sz_vec(1)).';
% y_vec = randperm(range_x(2), sz_vec(1)).';
x_vec = [1.60, 1.63, 1.70, 1.76, 1.80];
y_vec = 10.* exp(-3.*x_vec);
preci = 5;
n = length(x_vec);
F = zeros([n, n]);
for i = 1:n
F(i,i) = y_vec(i);
F(i,i) = round(F(i,i), preci);
end
% calculate the divided difference
for delta = 1:(n-1)
for i = 1:n
if i + delta > n
break;
end
j = i + delta;
F(i, j) = (F(i, j-1) - F(i+1, j)) ./ (x_vec(i) - x_vec(j));
F(i, j) = round(F(i, j), preci);
end
end
syms x
p = 0;
cur_prod = 1;
for i = 1:n
if i >= 2
cur_prod = cur_prod * (x - x_vec(i - 1));
end
p = p + cur_prod * F(1, i);
% disp(p);
end
p = simplify(p);
disp(latex(p))
p = matlabFunction(p);
min_num = min(x_vec);
max_num = max(x_vec);
total_value = 1000;
xi = linspace(min_num, max_num, total_value);
plot(x_vec, y_vec, 'o', xi, p(xi))
legend('Data points', 'Lagrange interpolation')
(which is the same as)
p = x.*(-1.3322403784e+1)+x.^2.*1.035253783e+1-x.^3.*3.6795665+x.^4.*5.0085e-1+6.6847830336
This result is nearly the same as in the book.

Experimental result and analysis
Test of interpolation
Random different points

>> all_in_one
(31*x^9)/20160 - (127*x^8)/1680 + (2293*x^7)/1440 - (2707*x^6)/144 + (393197*x^5)/2880 - (226591*x^4)/360 + (2304703*x^3)/1260 - (201361*x^2)/63 + (11981*x)/4 - 1111
symbolic function inputs: x
Elapsed time is 0.406410 seconds.
2*x + ((x - 8)*(x - 9))/2 - (2*(x - 7)*(x - 8)*(x - 9))/3 - (29*(x - 7)*(x - 8)*(x - 9)*(x - 10))/280 - ((x - 3)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/210 + (239*(x - 3)*(x - 4)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/5040 + (103*(x - 3)*(x - 4)*(x - 6)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/10080 + (13*(x - 2)*(x - 3)*(x - 4)*(x - 6)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/10080 + (31*(x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 6)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/20160 - 13
symbolic function inputs: x
Elapsed time is 0.198716 seconds.
It can be found that the oscillation is more obvious at the border.
Some real functions
sin(x)
>> all_in_one
(sin(2)*(x - 1)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/40320 - (sin(1)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/362880 - (sin(3)*(x/2 - 1/2)*(x - 2)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/5040 + (sin(4)*(x/3 - 1/3)*(x - 2)*(x - 3)*(x - 5)*(x - 6)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/1440 - (sin(5)*(x/4 - 1/4)*(x - 2)*(x - 3)*(x - 4)*(x - 6)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/720 + (sin(6)*(x/5 - 1/5)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 7)*(x - 8)*(x - 9)*(x - 10))/576 - (sin(7)*(x/6 - 1/6)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 8)*(x - 9)*(x - 10))/720 + (sin(8)*(x/7 - 1/7)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 9)*(x - 10))/1440 - (sin(9)*(x/8 - 1/8)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 8)*(x - 10))/5040 + (sin(10)*(x/9 - 1/9)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 8)*(x - 9))/40320
symbolic function inputs: x
Elapsed time is 0.939289 seconds.
(76365784749291*x)/1125899906842624 - (7530053351810631*(x - 1)*(x - 2))/18014398509481984 + (8481884696636481*(x - 1)*(x - 2)*(x - 3))/72057594037927936 + (1432589426173745*(x - 1)*(x - 2)*(x - 3)*(x - 4))/288230376151711744 - (7292257428457373*(x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5))/1152921504606846976 + (941795826732659*(x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6))/1152921504606846976 + (4599379538442441*(x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7))/147573952589676412928 - (2507741590142589*(x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 8))/147573952589676412928 + (1579577787439489*(x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 8)*(x - 9))/1180591620717411303424 + 3484185274626763/4503599627370496
symbolic function inputs: x
Elapsed time is 0.217115 seconds.

floor(log(x))
, range from 1 to 10
>> all_in_one
(x*(5*x^8 - 225*x^7 + 4260*x^6 - 44100*x^5 + 271131*x^4 - 1003275*x^3 + 2145460*x^2 - 2354400*x + 981144))/90720
symbolic function inputs: x
Elapsed time is 0.262802 seconds.
max(|f - g|) = 1.4724
var(|f - g|) = 0.11019
Elapsed time is 0.054497 seconds.
((x - 1)*(x - 2))/2 - ((x - 1)*(x - 2)*(x - 3))/3 + ((x - 1)*(x - 2)*(x - 3)*(x - 4))/8 - ((x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5))/30 + ((x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6))/144 - ((x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7))/1008 + ((x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 8)*(x - 9))/18144
symbolic function inputs: x
max(|f - g|) = 1.4724
var(|f - g|) = 0.11019
In this case, no significant error appears.

floor(log(x))
, range from 1 to 100

Lagrange interpolation:
Elapsed time is 19.243801 seconds.
max(|f - g|) = 2.791190982682177e+25
var(|f - g|) = 4.164987473892946e+48
Newton's interpolation:
Elapsed time is 0.226222 seconds.
max(|f - g|) = 8.322704101592106e+26
var(|f - g|) = 3.989048826417586e+51
In this case, Lagrange interpolation is slower but have a subtlety higher precision.
1/(1+x^2)
>> all_in_one
- x^10/44200 + (7*x^8)/5525 - (83*x^6)/3400 + (2181*x^4)/11050 - (149*x^2)/221 + 1
symbolic function inputs: x
Elapsed time is 0.328900 seconds.
max(|f - g|) = 1.9156
var(|f - g|) = 0.25155
Elapsed time is 0.032546 seconds.
(9*x)/442 + (23*(x + 4)*(x + 5))/2210 + (7*(x + 3)*(x + 4)*(x + 5))/1105 + (19*(x + 2)*(x + 3)*(x + 4)*(x + 5))/4420 - (9*(x + 1)*(x + 2)*(x + 3)*(x + 4)*(x + 5))/4420 - (x*(x + 1)*(x + 2)*(x + 3)*(x + 4)*(x + 5))/884 + (6*x*(x - 1)*(x + 1)*(x + 2)*(x + 3)*(x + 4)*(x + 5))/5525 - (19*x*(x - 1)*(x + 1)*(x - 2)*(x + 2)*(x + 3)*(x + 4)*(x + 5))/44200 + (x*(x - 1)*(x + 1)*(x - 2)*(x + 2)*(x - 3)*(x + 3)*(x + 4)*(x + 5))/8840 - (x*(x - 1)*(x + 1)*(x - 2)*(x + 2)*(x - 3)*(x + 3)*(x - 4)*(x + 4)*(x + 5))/44200 + 31/221
symbolic function inputs: x
max(|f - g|) = 1.9156
var(|f - g|) = 0.25155

Conclusion
In this experiment, we have implemented two methods for polynomial interpolation: Lagrange interpolation and Newton's interpolation. Both methods are useful for approximating a function when only a limited number of data points are available.
Lagrange interpolation involves constructing a polynomial that passes through all of the given data points. This polynomial is determined by using a set of basis polynomials, which are then weighted by scalar coefficients to produce the final polynomial. One advantage of Lagrange interpolation is that the resulting polynomial is unique, and therefore it can be used to perform a more accurate predict value of the function at any point within the range of the data points.
Newton's interpolation, on the other hand, involves constructing a polynomial using divided differences. This method allows for the efficient calculation of the polynomial coefficients, and therefore it can be used to interpolate functions even when the number of data points is large. Additionally, Newton's interpolation can be extended to handle unevenly spaced data points, which makes it a more versatile method than Lagrange interpolation in some cases.
Overall, both Lagrange interpolation and Newton's interpolation are powerful methods for approximating functions, and the choice between the two will depend on the specific requirements of the problem at hand.
Code
% initialization
clear;
preci = 10;
syms x
f(x) = 1/(1+x^2);
f_range = [-5, 5];
[x_vec, y_vec] = init(2, f, f_range);
tiledlayout(2,1);
total_value = 1000;
% lagrange interpolation
tic
p(x) = lagrange_interpolation(x_vec, y_vec);
disp(p);
toc
nexttile
show_graph(p, x_vec, y_vec, 1000, "lagrange interpolation");
error_analysis(f, p, f_range, total_value);
% newton's interpolation
tic
F = newtons_interpolation_init(x_vec, y_vec);
p(x) = newtons_interpolation(x_vec, F);
toc
disp(p);
nexttile
show_graph(p, x_vec, y_vec, 1000, "newtons interpolation");
error_analysis(f, p, f_range, total_value);
function [x_vec, y_vec] = init(init_type, f, f_range)
if init_type == 1
range_x = [0, 10];
sz_vec = [10, 1];
% randperm initialization
x_vec = randperm(range_x(2), sz_vec(1)).';
y_vec = randperm(range_x(2), sz_vec(1)).';
end
if init_type == 2
% real function initialization
f_min = min(f_range);
f_max = max(f_range);
x_vec = f_min:f_max;
x_vec = x_vec.';
y_vec = f(x_vec);
end
if init_type == 3
% example in textbook
x_vec = [1.60, 1.63, 1.70, 1.76, 1.80];
y_vec = 10 .* exp(-3 .* x_vec);
end
end
function p = lagrange_interpolation(x_vec, y_vec)
% Define the Lagrange basis polynomials
syms x;
L = sym('L', [1,length(x_vec)]);
n = length(x_vec);
for i = 1:n
L(i) = 1;
for j = 1:n
if j ~= i
L(i) = L(i) * (x - x_vec(j)) / (x_vec(i) - x_vec(j));
end
end
end
p = simplify(sum(y_vec.' .* L));
end
function F = newtons_interpolation_init(x_vec, y_vec)
n = length(y_vec);
F = zeros([n, n]);
% start to count time
tic
% calculate the divided difference
for i = 1:n
F(i,i) = y_vec(i);
% F(i,i) = round(F(i,i), preci);
end
for delta = 1:(n-1)
for i = 1:n
if i + delta > n
break;
end
j = i + delta;
F(i, j) = (F(i, j-1) - F(i+1, j)) ./ (x_vec(i) - x_vec(j));
% F(i, j) = round(F(i, j), preci);
end
end
end
function p = newtons_interpolation(x_vec, F)
% calculate the interpolation polynomial
n = length(x_vec);
syms x
p = 0;
cur_prod = 1;
for i = 1:n
if i >= 2
cur_prod = cur_prod * (x - x_vec(i - 1));
end
p = p + cur_prod * F(1, i);
% disp(p);
end
end
function show_graph(p, x_vec, y_vec, total_value, str)
min_num = min(x_vec);
max_num = max(x_vec);
xi = linspace(min_num, max_num, total_value);
plot(x_vec, y_vec, 'o', xi, p(xi));
legend('data points', str);
end
function error_analysis(f, g, f_range, total_value)
f_min = min(f_range);
f_max = max(f_range);
xi = linspace(f_min, f_max, total_value);
ei = double(abs(f(xi) - g(xi)));
max_dev = max(ei);
var_dev = var(ei);
disp("max(|f - g|) = " + num2str(max_dev));
disp("var(|f - g|) = " + num2str(var_dev));
end
本文来自博客园,作者:miyasaka,转载请注明原文链接:https://www.cnblogs.com/kion/p/17314618.html