实验五

实验内容

1、利用表中的数据给出分段厄米特插值结果:
Xi00.521.0471.57
hXi00.500.8661
h'Xi1.000.8660.5000
2、插值方法:从 y = F(x) = 5 cos(x) + 0.5randn(size(x)), x ∈[0, 3π] 中选取一些数据,在这些选取的数据上做 Lagrange 插值、牛顿差值、Hermitte 插值和样条插值。
3、使用 x = -3:3; y = [-1 -1 -1 0 1 1 1], 将 spline 和pchip 的插值结果进行比较并绘图。再采用振动采样函数,即执行 y=besselj(1,x), 重做前一步。
4、写出在 Matlab 中查询三次方样条数据插值 spline的步骤,并列出帮助中的所有语法? 采用数据 x = -4:4; y = [0 0.15 1.12 2.36 2.36 1.46 0.49 0.06 1] 做出样条函数并绘图。
5、多项式拟合: 已知 y = F(x) = 5 cos(x) + 0.5*randn(size(x)), x ∈[0, 3π], 从 y = F(x) 求出一组数据, 把 y = F(x) 拟合成三次多项式 P3(x) 的代码。


实验综述

本实验均基于 MATLAB 2019b 版本

安装MATLAB 2019b 点击查看

实验过程

利用表中的数据给出分段厄米特插值结果:
Xi00.521.0471.57
hXi00.500.8661
h'Xi1.000.8660.5000

实验代码
%% 利用表43中的数据给出分段厄米特插值结果:
%        Xi    0      0.52     1.047    1.57
%        hXi   0      0.50     0.866    1
%        h'Xi  1.00   0.866    0.500    0
%  版本 2019b
%  说明

%% 代码部分
clc,close,clear;
x = [0 0.52 1.047 1.57];
y = [0 0.50 0.866 1];
xq1 = [1.00 0.866 0.500 0];
X = 0:0.1:2;
p = hermite(x,y,xq1,X,1);
plot(x,y,'*',X,p,'r')
legend('样本点','厄米特插值')

%%  函数部分
%hermite.m
%求埃尔米特多项式和误差估计的MATLAB主程序
%输入的量:X是n+1个节点(x_i,y_i)(i = 1,2, ... , n+1)横坐标向量,Y是纵坐标向量,
%以f'(x_i)=y'_i(i = 1,2,...,n+1)为元素的向量Y1;
%x是以向量形式输入的m个插值点,M在[a,b]上满足|f~(2n+2)(x)|≤M
%注:f~(2n+2)(x)表示f(x)的2n+2阶导数
%输出的量:向量y是向量x处的插值,误差限R,2n+1阶埃尔米特插值多项式H_k及其系数向量
%H_c,误差公式wcgs及其系数向量Cw.
function[y,R,Hc,Hk,wcgs,Cw] = hermite(X,Y,Y1,x,M)
n = length(X);
m = length(x);
for t = 1 : m
    z = x(t);
    H = 0;
    q = 1;
    c1 = 1;
    for k = 1 : n
        s = 0;
        V = 1;
        for i = 1 : n
            if k ~= i
                s = s + (1/(X(k)-X(i)));
                V = conv(V,poly(X(i)))/(X(k)-X(i));
            end
        end
        h = poly(X(k));
        g = ([0 1]-2 * h * s);%注意不要写成1-2*h*s,因为是多项式减法,低阶多项式前面必须用零填补
        G = g * Y(k) + h * Y1(k);
        H = H + conv(G,conv(V,V));%hermite插值多项式
        b = poly(X(k));
        b2 = conv(b,b);
        q = conv(q,b2);
    end
    Hc = H;
    Hk = poly2sym(H);
    Q = poly2sym(q);
    for i = 1 : 2*n
        c1 = c1 * i;
    end
    wcgs = M * Q / c1;
    Cw = M * q / c1;
    y(t) = polyval(Hc,x(t));
    R(t) = polyval(Cw,x(t));
end
end
实验效果

插值方法:从 y = F(x) = 5 cos(x) + 0.5randn(size(x)), x ∈[0, 3π] 中选取一些数据,在这些选取的数据上做 Lagrange 插值、牛顿差值、Hermitte 插值和样条插值

实验代码
%% 插值方法. 从 y = F(x) = 5 cos(x) + 0.5randn(size(x)), x ∈[0, 3π] 中选取一些数据,
%  在这些选取的数据上做 Lagrange 插值、牛顿差值、Hermitte 插值和样条插值。
%  版本 2019b

%% 代码部分
clc,close,clear;
x = 0:0.3:3*pi;
y = cos(x) + rand(size(x));
X = 3*rand(1,4)*pi;
Y = cos(X) + rand(size(X));
X1 = 0:0.1:10;
y1 = lagrange(X,Y,X1);
y2 = newton(X,Y,X1,1);
y3 = pchip(X,Y,X1);
y4 = spline(X,Y,X1);
plot(X,Y,'o',X1,y1,'g',X1,y2,'--',X1,y2,'x',X1,y2),grid
legend('样本点','Lagrange 插值','牛顿差值','Hermitte 插值','样条插值')

%% 函数部分
function yy=lagrange(x1,y1,xx)
%本程序为Lagrange1插值,其中x1,y1
%为插值节点和节点上的函数值,输出为插值点xx的函数值,
%xx可以是向量。
syms x
n=length(x1);
for i=1:n
t=x1;t(i)=[];L(i)=prod((x-t)./(x1(i)-t));% L向量用来存放插值基函数
end
u=sum(L.*y1);
p=simplify(u); % p是简化后的Lagrange插值函数(字符串)
yy=subs(p,x,xx);    %p是以x为自变量的函数,并求xx处的函数值
end

function[y,R,A,C,L] = newton(X,Y,x,M)
n = length(X);
m = length(x);
for t = 1 : m
    z = x(t);
    A = zeros(n,n);
    A(:,1) = Y';
    s = 0.0; p = 1.0; q1 = 1.0; c1 = 1.0;
        for j = 2 : n
            for i = j : n
                A(i,j) = (A(i,j-1) - A(i-1,j-1))/(X(i)-X(i-j+1));
            end
            q1 = abs(q1*(z-X(j-1)));
            c1 = c1 * j;
        end
        C = A(n, n); q1 = abs(q1*(z-X(n)));
        for k = (n-1):-1:1
            C = conv(C, poly(X(k)));
            d = length(C);
            C(d) = C(d) + A(k,k);%在最后一维,也就是常数项加上新的差商
        end
        y(t) = polyval(C,z);
        R(t) = M * q1 / c1;
end
L = poly2sym(C);
end
实验效果

使用 x = -3:3; y = [-1 -1 -1 0 1 1 1], 将 spline 和pchip 的插值结果进行比较并绘图。再采用振动采样函数,即执行 y=besselj(1,x), 重做前一步

实验代码
%% 使用 x = -3:3; y = [-1 -1 -1 0 1 1 1], 将 spline 和pchip 的插值结果进行比较并绘图。
%   再采用振动采样函数,即执行 y=besselj(1,x), 重做前一步。
%  版本 2019b
%% 代码部分
clc,close,clear;
x = -3:3;
y = [-1 -1 -1 0 1 1 1];
xq1 = -3:.01:3;
p = pchip(x,y,xq1);
s = spline(x,y,xq1);
subplot(2,1,1);
plot(x,y,'o',xq1,p,'-',xq1,s,'-.')
title('spline 和 pchip 为两个不同函数生成的插值结果进行比较')
legend('样本点','埃尔米特插值','样条插值','Location','SouthEast')
x = 0:25;
y = besselj(1,x);
xq2 = 0:0.01:25;
p = pchip(x,y,xq2);
s = spline(x,y,xq2);
subplot(2,1,2)
plot(x,y,'o',xq2,p,'-',xq2,s,'-.')
title('使用振动采样函数执行第二次比较。')
legend('样本点','埃尔米特插值','样条插值')
实验效果

写出在 Matlab 中查询三次方样条数据插值 spline的步骤,并列出帮助中的所有语法? 采用数据 x = -4:4; y = [0 0.15 1.12 2.36 2.36 1.46 0.49 0.06 1] 做出样条函数并绘图

实验代码
%% 写出在 Matlab 中查询三次方样条数据插值 spline的步骤,并列出帮助中的所有语法?
%  采用数据 x = -4:4; y = [0 0.15 1.12 2.36 2.36 1.46 0.49 0.06 1] 做出样条函数并绘图。
%  版本 2019b
%  说明 :三次方样条数据插值 spline共有俩种
%  s = spline(x,y,xq)
%  pp = spline(x,y)
%  s = spline(x,y,xq) 返回与 xq 中的查询点对应的插值 s 的向量。s 的值由 x 和 y 的三次样条插值确定。
%  pp = spline(x,y) 返回一个分段多项式结构体以用于 ppval 和样条实用工具 unmkpp。
%  输入参数:
%  x 坐标:指定为向量。向量 x 指定提供数据 y 的点。x 的元素必须是唯一的。  数据类型: single 或 double
%  y 坐标:在 x 坐标处的函数值,指定为数值向量、矩阵或数组。x 和 y 通常具有相同的长度,但 y 也可以比 x 正好多出两个元素,用以指定端点斜率。
%          如果 y 是矩阵或数组,则在获取最后一个维度 y(:,...,:,j) 中的值时应使其匹配 x。
%          在此情况下,y 的最后一个维度的长度必须与 x 相同或正好多出两个元素。
%          三次样条的端点斜率遵循以下规则:
%          如果 x 和 y 是大小相等的向量,则使用非节终止条件。
%          如果 x 或 y 为标量,则会将该标量扩展为与另一方具有相同的长度并使用非节终止条件。
%          如果 y 是一个包含的值比 x 具有的条目多两个的向量,则 spline 使用 y 中的第一个和最后一个值作为三次样条的端点斜率。
%          例如,如果 y 是一个向量,则:
%          y(2:end-1) 给出 x 中每个点处的函数值
%          y(1) 给出区间开始处 min(x) 的斜率
%          y(end) 给出区间结束处 max(x) 的斜率
%          同样,如果 y 是一个矩阵或 size(y,N) 等于 length(x)+2 的 N 维数组,则:
%          y(:,...,:,j+1) 给出 x 中每个点的函数值,其中 j = 1:length(x)
%          y(:,:,...:,1) 给出区间开始处 min(x) 的斜率
%          y(:,:,...:,end) 给出区间结束处 max(x) 的斜率
%          数据类型: single | double
%  xq - 查询点  向量   查询点,指定为一个向量。xq 中指定的点是 spline 计算出的插值函数值 s 的 x 坐标。  数据类型: single | double
%% 代码部分
clc,close,clear;
x = -4:4;
y = [0 0.15 1.12 2.36 2.36 1.46 0.49 0.06 1];
cs = spline(x,[0 y 0]);
xx = linspace(-4,4,101);
plot(x,y,'o',xx,ppval(cs,xx),'-');
实验效果

多项式拟合: 已知 y = F(x) = 5 cos(x) + 0.5*randn(size(x)), x ∈[0, 3π], 从 y = F(x) 求出一组数据, 把 y = F(x) 拟合成三次多项式 P3(x) 的代码

实验代码
%% 多项式拟合:
%  已知 y = F(x) = 5 cos(x) + 0.5*randn(size(x)), x ∈[0, 3π],
%  从 y = F(x) 求出一组数据, 把 y = F(x) 拟合成三次多项式 P3(x) 的代码。
%  版本 2019b

%% 代码部分
clc,close,clear;
x = 0:0.3:3*pi;
y = cos(x) + rand(size(x));
P3 = polyfit(x,y,3);
P3d = poly2str(P3,'x')   %三次拟合多项式
plot(x,y,'*'),grid,hold
fplot(@(x) P3(1)*x^3 + P3(2)*x^2 + P3(3)*x + P3(4),[0 10])
axis([0 10 -2 2])
legend('样本点','拟合曲线 P_3(x)')
实验效果