第一种三次样条函数的Matlab求解

来源:李庆杨等第五版《数值分析》P44页例题。目的:回顾一下matlab的基本用法。

首先根据书中给出的数学表达式编写求解弯矩(书上这么叫的)函数:

function [M,A,d,H] = SolveSpline_1(x,y,diff_y0,diff_yn)
    %Function:求解第一种三次样条函数插值
    %变量说明:
	%Input varibles:
		% x:自变量数据(以列的形式输入)
		% y:因变量数据(以列的形式输入)
		% diff_y0:左端点导数值
		% diff_yn:右端点到数值
	%Output varibles:
		%M:三次样条函数中的弯矩
		%A:三对角矩阵
		%d:右端向量
		%H:节点步长

    xx = x(2:end);
    a = x(1);%作为x0点
    [n,m] = size(xx);

    A = 2*eye(n+1,n+1);%初始化三对角矩阵

    H = diff(x);
    %对角参数设置
    mu = zeros(n,1);
    mu(n) = 1;
    for k = [1:n-1]
        mu(k) = H(k)/(H(k) + H(k+1));
    end

    lambda = zeros(n,1);
    lambda(1) = 1;
    for k = [2:n]
        lambda(k) = H(k)/(H(k-1) + H(k)); 
    end

    d = zeros(n+1,1);
    %temp = (y(2) - y(1))/(x(2) - x(1))
    d(1) = (6/H(1))*((y(2) - y(1))/(x(2) - x(1)) - diff_y0);
    %temp = diff_yn - ((y(end) - y(end-1))/(x(end) - x(end-1)))
    d(n+1) = (6/H(n))*(diff_yn - ((y(end) - y(end-1))/(x(end) - x(end-1))));
    for k = [2:n]
        %temp = (y(k+1) - y(k))/(x(k+1) - x(k))
        %temp = (y(k) - y(k-1))/(x(k) - x(k-1))
        d(k) = 6*((y(k+1) - y(k))/(x(k+1) - x(k)) - (y(k) - y(k-1))/(x(k) - x(k-1)))/(x(k+1) - x(k-1));
    end
    
    %给出三对角矩阵
    A = A + diag(mu,-1) + diag(lambda,1);
    %求解M
    M = A^(-1)*d;
end

%这样求解完 M 后,便可将 M 带入到三次样条函数表达式中去,从而便得出了小区间上的三次样条插值函数

再编写主函数并绘制三次样条插值函数的图像,如下:

clc,clear all
x = [27.7,28,29,30]';
y = [4.1,4.3,4.1,3.0]';
diff_y0  = 3.0;
diff_yn = -4.0;
[M,A,d,H] = SolveSpline_1(x,y,diff_y0,diff_yn);

%利用分段函数的写法给出三次样条插值函数
[n,m] = size(x);
n = n-1;
t = [27.7:0.001:30];
S = 0;
for k = [1:n]

%{
    temp = (x(k+1) - t).^3./(6*H(k))
    temp = (t - x(k)).^3./(6*H(k))
    temp = y(k) - M(k)*H(k)^2/6
    temp = (x(k+1) - t)/H(k)
    temp = y(k+1) - M(k+1)*H(k)^2/6
    temp = x(k+1) - t
    temp = (t - x(k+1))./H(k) 
%}
    
    S = S + (M(k)*((x(k+1) - t).^3./(6*H(k))) + M(k+1)*((t - x(k)).^3./(6*H(k))) ... 
        + (y(k) - M(k)*H(k)^2/6).*((x(k+1) - t)/H(k)) + (y(k+1) - M(k+1)*H(k)^2/6).*((t - x(k))./H(k))).*(t > x(k) & t < x(k+1));
end

figure
title('Demo about spline');
hold on
plot(t,S);
scatter(x,y)
hold off
xlabel('X');
ylabel('Y');
legend('spline function','previous points')
grid on;

最后,简单的绘图结果如下:

第一种三次样条函数的Matlab求解