1. 程式人生 > 實用技巧 >樣條之拉格朗日Lagrange(一元全區間)插值函式[轉]

樣條之拉格朗日Lagrange(一元全區間)插值函式[轉]

樣條之拉格朗日Lagrange(一元全區間)插值函式

這是使用拉格朗日插值函式生成的樣條曲線。在數值分析中,拉格朗日插值法是以法國十八世紀數學家約瑟夫·拉格朗日命名的一種多項式插值方法。許多實際問題中都用函式來表示某種內在聯絡或規律,而不少函式都只能通過實驗和觀測來了解。如對實踐中的某個物理量進行觀測,在若干個不同的地方得到相應的觀測值,拉格朗日插值法可以找到一個多項式,其恰好在各個觀測的點取到觀測到的值。這樣的多項式稱為拉格朗日(插值)多項式。數學上來說,拉格朗日插值法可以給出一個恰好穿過二維平面上若干個已知點的多項式函式。

關於插值與樣條的介紹請看:http://www.cnblogs.com/WhyEngine/p/4020294.html

核心程式碼:

//////////////////////////////////////////////////////////////////////
// 一元全區間等距插值
//////////////////////////////////////////////////////////////////////
static float GetValueLagrange(const void* valuesPtr, int stride, int n, float t)
{ 
    int i,j,k,m;
    float z,s,xi,xj;
    float p,q;

    // 初值
    z = 0.0f;

    // 特例處理
    if (n < 1) 
    {
        return(z);
    }
    if (n == 1) 
    { 
        z = YfGetFloatValue(valuesPtr, stride, 0); 
        return(z);
    }
    if (n == 2)
    { 
        float y0 = YfGetFloatValue(valuesPtr, stride, 0); 
        float y1 = YfGetFloatValue(valuesPtr, stride, 1); 
        z = y0 + (y1 - y0)*t;
        return(z);
    }

    float xStep = 1.0f/(n - 1);

    // 開始插值
    if (t > 0.0f)
    { 
        p = t/xStep; 
        i = (int)p; 
        q = (float)i;

        if (p > q) 
        {
            i = i+1;
        }
    }
    else 
    {
        i = 0;
    }

    k = i-4;
    if (k < 0) 
    {
        k = 0;
    }

    m = i+3;
    if (m > n-1) 
    {
        m = n-1;
    }

    for (i = k; i <= m; i++)
    { 
        s = 1.0; 
        xi = i*xStep;

        for (j = k; j <= m; j++)
        {
            if (j != i)
            { 
                xj = j*xStep;
                // 拉格朗日插值公式
                s = s*(t-xj)/(xi-xj);
            }
        }

        z = z + s*YfGetFloatValue(valuesPtr, stride, i); 
    }

    return(z);
}

這是神一樣的程式碼,反正我這輩子估計是看不懂了。

切圖:

相關軟體的下載地址為:http://files.cnblogs.com/WhyEngine/TestSpline.zip