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

时间:2017-07-09 11:08:16

标签: matlab interpolation derivative

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

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 个答案:

答案 0 :(得分:2)

方法A:使用衍生物

此方法计算多项式的实际导数。如果您有曲线拟合工具箱,则可以使用:

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); 行替换为:

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

来源:This mathworks question感谢m7913d链接它。

<强>附录

请注意

% 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);

为了得到导数,我们显然需要多项式,而不能只使用新的插值点。为避免将点插值两次(对于大量数据需要很长时间),您应该用较长版本替换快捷方式。因此,包含代码示例的完整工作示例将是:

eps

方法B:使用有限差分

连续函数的导数只是f(x)与f(x +无穷小差)之差除以所述无穷小差异。

在matlab中,t_new是双精度可能的最小差异。因此,在每个eps之后,我们添加第二个点y,并为新点插入% 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); 。然后,每个点与它的+ eps对除以eps之间的差异给出了导数。

问题在于,如果我们处理这么小的差异,输出导数的精度会受到严格限制,这意味着它只能有整数值。因此,我们添加略大于eps的值,以允许更高的精度。

t_new

如果你想在旧点获得衍生品,你当然可以用t(或任何其他想要获得差异的时间)替换{{1}}。

这种方法在你的情况下略逊于方法a),因为它比较慢而且不太精确。但也许这对处于不同情况的其他人有用。