代码之家  ›  专栏  ›  技术社区  ›  Alex

样条插值及其(精确)导数

  •  2
  • Alex  · 技术社区  · 7 年前

    假设我有以下数据和命令:

    clc;clear;
    t = [0:0.1:1];
    t_new = [0:0.01:1];
    y = [1,2,1,3,2,2,4,5,6,1,0];
    p = interp1(t,y,t_new,'spline');
    plot(t,y,'o',t_new,p)
    

    可以看到,它们工作得很好,从某种意义上说,插值函数与节点处的数据点匹配得很好。但我的问题是,我需要计算y(即p函数)w.r.t.时间的精确导数,并将其与t向量作图。怎么做?我将不使用diff命令,因为我需要确保导数函数的长度与t向量相同。谢谢。

    1 回复  |  直到 7 年前
        1
  •  5
  •   Leander Moesinger    7 年前

    方法A:使用导数

    % calculate the polynominal
    pp = interp1(t,y,'spline','pp')
    % take the first order derivative of it
    pp_der=fnder(pp,1);
    % evaluate the derivative at points t (or any other points you wish)
    slopes=ppval(pp_der,t);
    

    如果没有曲线拟合工具箱,可以替换 fnder 符合:

    % piece-wise polynomial
    [breaks,coefs,l,k,d] = unmkpp(pp);
    % get its derivative
    pp_der = mkpp(breaks,repmat(k-1:-1:1,d*l,1).*coefs(:,1:k-1),d);
    

    This mathworks question . 感谢m7913d的链接。

    附录:

    p = interp1(t,y,t_new,'spline');
    

    是的快捷方式

    % get the polynomial 
    pp = interp1(t,y,'spline','pp');
    % get the height of the polynomial at query points t_new
    p=ppval(pp,t_new);
    

    t = [0:0.1:1];
    t_new = [0:0.01:1];
    y = [1,2,1,3,2,2,4,5,6,1,0];
    
    % fit a polynomial 
    pp = interp1(t,y,'spline','pp');
    % get the height of the polynomial at query points t_new
    p=ppval(pp,t_new);
    % plot the new interpolated curve
    plot(t,y,'o',t_new,p)
    
    % piece-wise polynomial
    [breaks,coefs,l,k,d] = unmkpp(pp);
    % get its derivative
    pp_der = mkpp(breaks,repmat(k-1:-1:1,d*l,1).*coefs(:,1:k-1),d);
    % evaluate the derivative at points t (or any other points you wish)
    slopes=ppval(pp_der,t);
    

    方法B:使用有限差分法

    一个连续函数的导数在其基部就是f(x)到f(x+无穷小差)的差除以所述无穷小差。

    在matlab中, eps 是具有双精度的最小差异。因此在每次 t_new 我们添加第二点,即 放大并插值 y 对于新点。然后,每个点与其+eps对之间的差除以eps得到导数。

    % how many floating points the derivatives can have
    precision = 10;
    % add after each t_new a second point with +eps difference
    t_eps=[t_new; t_new+eps*precision];
    t_eps=t_eps(:).';
    % interpolate with those points and get the differences between them
    differences = diff(interp1(t,y,t_eps,'spline'));
    % delete all differences wich are not between t_new and t_new + eps
    differences(2:2:end)=[];
    % get the derivatives of each point
    slopes = differences./(eps*precision);
    

    t\u新 具有 t (或任何其他你想得到的微分)如果你想得到旧点的导数。