4

For a LPC922 microcontroller (with SDCC) I want to create a lookup table with linear interpolation. Lets assume I got x and y values like

x=300 y=10,0201 
x=700 y=89,542 
x=800 y=126,452 
x=900 y=171,453 
x=1500 y=225,123

How can the code for a lookup table with linear interpolation look like, so I get for example for x=850 the right value for y ((171,453+126,452)/2)?

4

3 回答 3

5
typedef struct { double x; double y; } coord_t;

coord_t c[5] = 
{
    {300, 10.02},
    {700, 89.542},
    {800, 126.452}, 
    {900, 171.453}, 
    {1500,225.123}
};    

double interp( coord_t* c, double x, int n )
{
    int i;

    for( i = 0; i < n-1; i++ )
    {
        if ( c[i].x <= x && c[i+1].x >= x )
        {
            double diffx = x - c[i].x;
            double diffn = c[i+1].x - c[i].x;

            return c[i].y + ( c[i+1].y - c[i].y ) * diffx / diffn; 
        }
    }

    return 0; // Not in Range
}

int main(int argc, char** argv) 
{
    double y = interp( c, 850, 5 );
}
于 2011-08-17T11:06:40.480 回答
2
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));
}
于 2011-08-17T10:55:23.957 回答
0

将所有值放在一个数组中。然后搜索 x.. 如果你没有找到正确的值,你有一个索引和一个邻居索引,然后使用你的公式计算值..

于 2011-08-17T10:34:01.080 回答