gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 03:52:29 37 4
gpt4 key购买 nike

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

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 向量具有相同的长度。多谢。

最佳答案

方法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 是 double 可能的最小差异。因此,在每个t_new之后,我们添加一个eps更大的第二个点,并为新点插入y。然后每个点和它的 +eps 对之间的差除以 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_new 替换为 t (或您想要获得微分的任何其他时间)。

在您的情况下,此方法稍逊于方法 a),因为它速度较慢且精度稍差。但也许这对其处于不同情况的其他人有用。

关于matlab - 样条插值及其(精确)导数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44995725/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com