double get_value(double x)
{
/* NOTE: xs MUST be sorted */
static const double xs[] = { 300, 700, 800, 900, 1500 };
static const double ys[] = { 10.0201, 89.542, 126.452, 171.453, 225.123 };
/* number of elements in the array */
static const int count = sizeof(xs)/sizeof(xs[0]);
int i;
double dx, dy;
if (x < xs[0]) {
/* x is less than the minimum element
* handle error here if you want */
return ys[0]; /* return minimum element */
}
if (x > xs[count-1]) {
return ys[count-1]; /* return maximum */
}
/* find i, such that xs[i] <= x < xs[i+1] */
for (i = 0; i < count-1; i++) {
if (xs[i+1] > x) {
break;
}
}
/* interpolate */
dx = xs[i+1] - xs[i];
dy = ys[i+1] - ys[i];
return ys[i] + (x - xs[i]) * dy / dx;
}
如果您愿意,这可以很容易地扩展到其他插值方法。请注意,您可能必须扩展边界区域的特殊情况,但您希望处理它。一种常见的方法是在没有足够的相邻值可用于首选方法时进行线性插值。
此外,当值的数量开始增长时,我建议使用二进制搜索方法来计算起点。不过,这不应该是这几个值的问题。
更新:由于 OP 在有限的平台上工作,这是使用libfixmath的上述版本:
/* NOTE: xs MUST be sorted */
static const fix16_t xs[] = { 300<<16, 700<<16, 800<<16, 900<<16, 1500<<16 };
static const fix16_t ys[] = { (fix16_t)(65536.0*10.0201+0.5), (fix16_t)(65536.0*89.542+0.5), (fix16_t)(65536.0*126.452+0.5), (fix16_t)(65536.0*171.453+0.5), (fix16_t)(65536.0*225.123+0.5) };
fix16_t get_value_fix(fix16_t x)
{
/* number of elements in the array */
static const int count = sizeof(xs)/sizeof(xs[0]);
int i;
fix16_t dx, dy;
if (x < xs[0]) {
/* x is less than the minimum element
* handle error here if you want */
return ys[0]; /* return minimum element */
}
if (x > xs[count-1]) {
return ys[count-1]; /* return maximum */
}
/* find i, such that xs[i] <= x < xs[i+1] */
for (i = 0; i < count-1; i++) {
if (xs[i+1] > x) {
break;
}
}
/* interpolate */
dx = fix16_sub(xs[i+1], xs[i]);
dy = fix16_sub(ys[i+1], ys[i]);
return fix16_add(ys[i], fix16_div(fix16_mul(fix16_sub(x, xs[i]), dy), dx));
}