cubic Spline Interpolation - 三次样条插值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在MATLAB上按照非结点边界条件三次样条插值,并于自带的interp1函数对比,代码如下:

%测试文件
clc
clear all; close all;

%% 测试6个点的三次样条插值
slen = 6;
x = 1 : slen;
y = rand(1,slen)*10;
xi = 1 : 0.1 : slen;
yi = interp1(x, y, xi, 'slpine');


yii = interp1Test(x, y, xi);
figure
plot(x,y,'*-', xi, yi, 'r*-', xi, yii, 'bo-');
legend('origin data','matlab interp1','cubic interolation-not a knot');
title('interpolation')
function [yi] = interp1Test(x, y, xi)
% 测试spline插值
% 输入 - x: 距离, y: 函数值 , xi 待插值点
% 输出 - yi: 待插值点的函数值

sizex = (size(x));
sizey = (size(y));
if ~(sizex(1)*sizex(2)==sizex(1) || sizex(1)*sizex(2)==sizex(2)) || ~(sizey(1)*sizey(2)==sizey(1) || sizey(1)*sizey(2)==sizey(2))
    error('the input x or y must be one dimension')
end

if length(x) ~= length(y)
    error('the lenth of x or y must be same');
end

% 输入的长度
len = length(x);  
hi = zeros(1, len - 1);
hi = x(2:end) - x(1:end-1);

mi = zeros(1, len - 1);
% 非结点边界的终止条件
A = zeros(len , len );
A(1, 1) = - hi(2); A(1,2) = hi(1)+hi(2); A(1,3) = -hi(1);
A(len , len - 2) = -hi(len-1); A(len , len - 1) = hi(len-1)+hi(len-2);  A(len , len ) = -hi(len-2);
for i = 2 : len - 1
    A(i, i-1) = hi(i-1);
    A(i, i) = 2 * (hi(i-1) + hi(i));
    A(i, i+1) = hi(i);
end

Bm = zeros(len, 0);
Bm(1,1) = 0;
Bm(len,1) = 0;
for i = 2 : len - 1
    Bm(i,1) = 6 * ((y(i+1)-y(i))/hi(i) - (y(i)-y(i-1))/hi(i-1));
end

% Ax = B
mi = A\Bm;

a = zeros(1, len-1);
b = zeros(1, len-1);
c = zeros(1, len-1);
d = zeros(1, len-1);
for i = 1 : len-1
    a(i) = y(i);
    b(i) = (y(i+1)-y(i))/hi(i) - hi(i)*mi(i)/2 - hi(i)*(mi(i+1)-mi(i))/6;
    c(i) = mi(i)/2;
    d(i) = (mi(i+1)-mi(i))/6/hi(i);
end

yi = zeros(1, length(xi));
for i = 1 : length(xi)
    xIndex = 0;
    for j = 1 : 1 : length(x)
        if xi(i) - x(j) >= 0
            xIndex = j;
        end
    end
    fprintf(2, 'xIndex = %d\n', xIndex);
    if xIndex >= 1 && xIndex < length(x)
        yi(i) = a(xIndex) + b(xIndex) * (xi(i) - x(xIndex)) + c(xIndex) * (xi(i) - x(xIndex))^2 +d(xIndex) * (xi(i) - x(xIndex))^3;
    end
    if xIndex >= length(x)
        yi(i) = a(len-1) + b(len-1) * (xi(i) - x(len-1)) + c(len-1) * (xi(i) - x(len-1))^2 +d(len-1) * (xi(i) - x(len-1))^3;
    end
     if xIndex < 1
        yi(i) = a(1) + b(1) * (xi(i) - x(1)) + c(1) * (xi(i) - x(1))^2 +d(1) * (xi(i) - x(1))^3;
    end
end


end

对比结果显示如图所示:
在这里插入图片描述
在interp1Test.m文件中,计算方程组Ax = B是通过A\B来计算得出的,使用了MATLAB自带的函数,也可以自行编写代码将A转化成上三角阵,求得方程组的解,如下两段代码所示。这两段代码均是求解方程组,第二段代码使用了方程组的已知信息,不考虑系数矩阵A中值为0的区域。

function [mi] = solvingEquat(A,B)
% 求解方程组
% A - [n,n]系数矩阵 B- [n,1]

if size(A,1)~=size(A,2) || size(A,1) ~= size(B,1) || size(B,2)~=1
    error('the input x or y error')
end

% 将A , B放在同一个矩阵中
C = [A, B];
len = size(A,1);

% 将C转化为上三角矩阵,且置对角线的元素值为1
for i = 1 : len-1
    % 对角线元素不能为0,如为0,移动行使对角线元素不为0
    if C(i,i) == 0
        for j = i+1 : len
            if C(j,i) ~=0
                C([j, i], :) = C([i, j], :);
            end
        end
    end 
     if C(i,i) == 0
        continue;
    end
    if i == 1
        C(1, :) =  C(1, :) / C(1, 1);
    end
    for k = i+1 : len
        C(k,:) = C(k,:) - C(i,:) * C(k,i) / C(i,i);
        if abs(C(k,i+1))>0 
            C(k,:) = C(k,:) / C(k,i+1);
        end
    end
    
end

mi = zeros(1, len);
% 直接求出mi的最后一个值
mi(len) = C(len, len + 1);
% 逆向迭代,求出mi
for i = len-1:-1:1
    for j = len : -1 : i+1
        mi(i) =  mi(i) + mi(j) * C(i, j);
    end
    mi(i) = C(i, len + 1) - mi(i);
end

end
function [mi] = solvingEquat2(A,B)
% 求解方程组
% A - [n,n]系数矩阵 B- [n,1]
% 非结点边界, 不考虑系数矩阵A中值为0的区域

if size(A,1)~=size(A,2) || size(A,1) ~= size(B,1) || size(B,2)~=1
    error('the input x or y error')
end

len = size(A,1);
if len < 4
    error('the length of A can not smaller than 4!')
end
% initial
a = zeros(1, len);
b = zeros(1, len);
c = zeros(1, len);
d = zeros(1, len);

for i =  1 : len
    if i == 1
        a(i) = A(i, i);
        b(i) = A(i, i+1);
        c(i) = A(i, i+2);
    end
    if i >= 2 && i < len
        a(i) = A(i, i-1);
        b(i) = A(i, i);
        c(i) = A(i, i+1);
    end
    if i == len
        a(i) = A(i, i-2);
        b(i) = A(i, i-1);
        c(i) = A(i, i);
    end
    d(i) = B(i);
end

% 转化为上三角矩阵
b(1) = b(1) / a(1);
c(1) = c(1) / a(1);
d(1) = d(1) / a(1);

tmp = b(2) - a(2) * b(1);
c(2) = (c(2) - a(2) * c(1)) / tmp;
d(2) =  (d(2) - a(2) * d(1))/ tmp;

for i = 3 : len-1
    tmp = b(i) - a(i) * c(i - 1);
    c(i) = (c(i)) / tmp;
    d(i) = (d(i) - d(i-1) * a(i)) / tmp;
end

% tmp = b(len) - a(len) * c(len - 2);
b(len) = b(len) - a(len) * c(len-2);
d(len) = d(len) - a(len) * d(len-2);

tmp = c(len) - b(len) * c(len-1);
c(len) = (c(len) - b(len) * c(len-1))/tmp;
d(len) = (d(len) - d(len-1) * b(len))/tmp;

% 直接求出mi的最后一个值
mi(len) = d(len);
% 逆向迭代,求出mi
for i = len -1 : -1 : 2
    mi(i) = d(i) - c(i) * mi(i+1);
end
mi(1) = (d(1) - b(1) * mi(2) - c(1) * mi(3));

end
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值