Scilab中的样条系数

时间:2015-12-24 22:35:03

标签: interpolation spline scilab

我希望将一个分段三次样条拟合到一大组数据中。我不认为我想要B样条,因为我希望样条曲线完全通过数据点。我在Scilab中看到的唯一方法是使用splininterp

但是,我想要在结点之间的每个样条曲线的系数(因为我需要采用这些系数并将它们放在不同的软件中)。所有splin给你的是衍生物。有没有办法得到三次样条系数?或者有没有办法轻易地从一阶导数生成系数?

1 个答案:

答案 0 :(得分:1)

是的,可以从您拥有的y值和splin返回的派生值中获得系数。每个区间[x(i),x(i + 1)]有4个要查找的系数,4个方程:两端的值,两端的导数。最直接的方法是告诉Scilab为每个子区间解决这个4乘4系统:这不应该比样条本身的评估花费更长的时间。下面的程序就是这样做的。

x = [0,1,2,3,4,5]   // x values
y = [1,0,1,0,1,0]   // y values
d = splin(x,y)      
n = length(x)-1     // number of subintervals
cfs = zeros(4,n)    // matrix to store coefficients in
for i=1:n
    a = x(i)
    b = x(i+1)
    cfs(:,i) = [1,a,a^2,a^3; 1,b,b^2,b^3; 0,1,2*a,3*a^2; 0,1,2*b,3*b^2] \ [y(i);y(i+1);d(i);d(i+1)]
end

前两个方程1,a,a^2,a^3; 1,b,b^2,b^3将多项式的值与y值相关联;另外两个0,1,2*a,3*a^2; 0,1,2*b,3*b^2对其衍生物做同样的事情。 (公式只是x的幂的导数。)

上述脚本的输出:

    1.     1.   - 8.6    13.     13.   
  - 3.4  - 3.4    11.  - 10.6  - 10.6  
    3.1    3.1  - 4.1    3.1     3.1   
  - 0.7  - 0.7    0.5  - 0.3   - 0.3   

每列具有四个系数:例如,样条的第一个片段是1-3.4x+3.1x^2-0.7x^3。由于这是一个非结节样条,splin命令的默认模式,第二部分与第一部分相同;最后一个与倒数第二个相同。

您可以通过绘制片段来检查这是否正常:

for i=1:n  
    t = linspace(x(i),x(i+1))
    plot(t,cfs(:,i)'*[ones(t); t; t.^2; t.^3])
end

也就是说,用

形式表示形成样条的多项式会更容易
 p(x) = y(i) + A*(x-x(i)) + B*(x-x(i))*(x-x(i+1)) + C*(x-x(i))^2*(x-x(i+1))

在不解决线性系统的情况下,系数很容易逐个找到:

  • A = (y(i+1)-y(i))/(x(i+1)-x(i))将x(i + 1)
  • 的值等同
  • B = (d(i)-A)/(x(i)-x(i+1)),将衍生物等同于x(i)
  • C = (d(i+1)-A-B*(x(i+1)-x(i)))/(x(i+1)-x(i))^2,将衍生物等同于x(i + 1)

当然,这些系数应该与上面适当的多项式一起使用。这是替代版本

for i=1:n
    A = (y(i+1)-y(i))/(x(i+1)-x(i))
    B = (d(i)-A)/(x(i)-x(i+1))
    C = (d(i+1)-A-B*(x(i+1)-x(i)))/(x(i+1)-x(i))^2
    cfs(:,i) = [y(i);A;B;C]
end
// Again, plot for testing
for i=1:n
    t = linspace(x(i),x(i+1))
    plot(t,cfs(:,i)'*[ones(t); t-x(i); (t-x(i)).*(t-x(i+1)); ((t-x(i)).^2).*(t-x(i+1))])
end