任何人都可以指导我使用样条插值复制 MATLAB 的 interp1 函数吗?我尝试在 wikipedia page 上仔细复制算法,但结果并不完全匹配。
#include <stdio.h>
#include <stdint.h>
#include <iostream>
#include <vector>
//MATLAB: interp1(x,test_array,query_points,'spline')
int main(){
int size = 10;
std::vector<float> test_array(10);
test_array[0] = test_array[4] = test_array[8] = 1;
test_array[1] = test_array[3] = test_array[5] = test_array[7] = test_array[9] = 4;
test_array[2] = test_array[6] = 7;
std::vector<float> query_points;
for (int i = 0; i < 10; i++)
query_points.push_back(i +.05);
int n = (size - 1);
std::vector<float> a(n+1);
std::vector<float> x(n+1); //sample_points vector
for (int i = 0; i < (n+1); i++){
x[i] = i + 1.0;
a[i] = test_array[i];
}
std::vector<float> b(n);
std::vector<float> d(n);
std::vector<float> h(n);
for (int i = 0; i < (n); ++i)
h[i] = x[i+1] - x[i];
std::vector<float> alpha(n);
for (int i = 1; i < n; ++i)
alpha[i] = ((3 / h[i]) * (a[i+1] - a[i])) - ((3 / h[i-1]) * (a[i] - a[i-1]));
std::vector<float> c(n+1);
std::vector<float> l(n+1);
std::vector<float> u(n+1);
std::vector<float> z(n+1);
l[0] = 1.0;
u[0] = z[0] = 0.0;
for (int i = 1; i < n; ++i){
l[i] = (2 * (x[i+1] - x[i-1])) - (h[i-1] * u[i-1]);
u[i] = h[i] / l[i];
z[i] = (alpha[i] - (h[i-1] * z[i-1])) / l[i];
}
l[n] = 1.0;
z[n] = c[n] = 0.0;
for (int j = (n - 1); j >= 0; j--){
c[j] = z[j] - (u[j] * c[j+1]);
b[j] = ((a[j+1] - a[j]) / h[j]) - ((h[j] / 3) * (c[j+1] + (2 * c[j])));
d[j] = (c[j+1] - c[j]) / (3 * h[j]);
}
std::vector<float> output_array(10);
for (int i = 0; i < n-1; i++){
float eval_point = (query_points[i] - x[i]);
output_array[i] = a[i] + (eval_point * b[i]) + ( eval_point * eval_point * c[i]) + (eval_point * eval_point * eval_point * d[i]);
std::cout << output_array[i] << std::endl;
}
system("pause");
return 0;
}
最佳答案
事后看来,您的代码似乎是引用维基百科文章正确编码的。但是,关于 interp1
,您需要了解一些信息我认为您在使用它检查答案时没有考虑到这一点。
MATLAB 的 interp1
当您指定 spline
flag 假定终点条件是 not-a-knot。维基百科上指定的算法是自然样条的代码。
因此,这可能就是您的点数不匹配的原因。 FWIW,咨询:http://www.cs.tau.ac.il/~turkel/notes/numeng/spline_note.pdf并查看最后一页的图表。您会看到非结样条曲线和自然样条曲线具有相同的形状,但当您的数据仅包含样条曲线的端点时具有不同的 y 值。但是,如果端点之间有数据点,则所有不同类型的样条(或多或少)都具有相同的 y 值。
为了完整起见,这里是从我上面引用的 PDF 注释中提取的图:
如果您想使用自然样条,请使用 csape
而不是 interp1
.这提供了三次样条具有结束条件。你打电话csape
像这样:
pp = csape(x,y);
x
和 y
是为样条曲线定义的控制点。默认情况下,这会返回一个 natural 样条,这就是您所追求的,并且是 ppform
类型的结构。 .然后,您可以使用 fnval
计算出样条的计算结果。 :
yval = fnval(pp, xval);
xval
和 yval
是输入 x
在这个特定的 x
处为样条曲线评估的坐标和输出.
使用它,然后检查您的代码是否与 csape
提供的值匹配.
小注
您需要 MATLAB 中的曲线拟合工具箱才能使用 csape
.如果你没有这个,那么不幸的是这个方法将不起作用。
关于C++:复制matlab的interp1样条插值函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24706002/