2011-08-17 60 views
3

对于LPC922微控制器(使用SDCC),我想创建一个带有线性插值的查找表。 让我们假设我有X和Y值一样如何使用线性插值在C(SDCC编译器)中构建查找表

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 

如何用线性插值的样子查找表的代码一样,所以我得到例如用于X = 850权值Y((171453 + 126452 )/ 2)?

回答

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); 
} 
0

将所有值放入数组中。然后搜索X ..如果你没发现你有一个索引和邻居索引,然后使用您的公式计算值正确的值..

+0

但如何找到索引和邻居指标,如果我不能找到正确的价值? – Stefan 2011-08-17 10:48:00

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; 
} 

这可以很容易地扩展到其他interpolation methods如果你希望。请注意,您可能需要扩展边界区域的特殊情况,但是您希望处理该情况。当没有足够的相邻值可用于首选方法时,常用的方法是进行线性插值。

此外,当值的数量开始增加,我会建议使用binary search方法来计算出发点。尽管如此,这应该不是问题。

更新:由于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)); 
} 
+0

非常感谢你,我将尝试你的代码。 – Stefan 2011-08-17 11:11:32