C#版本拉格朗日插值演算法

來源:互聯網
上載者:User

        實際中有時需要對資料進行分析, 最近就遇到了這樣一個情況: 有一系列橫座標是時間, 縱座標是記錄值的一些資料, 但橫座標卻不是等距記錄的. 就是說在第一分鐘記錄一次, 第二分鐘記錄一次, 第四分鐘記錄一次...不等距. 需求是根據現在的這些資料進行計算, 獲得等距時間所對應的記錄值, 也就是說第三分鐘沒有記錄, 得通過計算來獲得第三分鐘的值.

        原本想把這些資料顯示在Chart控制項中, 然後再從Chart控制項中擷取各個X座標所對應的Y值, 但後來發現這樣不可行, 只能得到有記錄的資料點的值, 新點的值得不到. 只能使用插值來計算了, 下面是拉格朗日插值的演算法(C#版本):

/// <summary>/// 根據離散點進行二次的拉格朗日插值/// http://www.cnblogs.com/technology/// </summary>class Lagrange{/// <summary>/// X各點座標組成的數組/// </summary>public int[] x { get; set; }/// <summary>/// X各點對應的Y座標值組成的數組/// </summary>public double[] y { get; set; }/// <summary>/// x數組或者y數組中元素的個數, 注意兩個數組中的元素個數需要一樣/// </summary>public int itemNum { get; set; }/// <summary>/// 初始化拉格朗日插值/// </summary>/// <param name="x">X各點座標組成的數組</param>/// <param name="y">X各點對應的Y座標值組成的數組</param>public Lagrange(int[] x, double[] y){    this.x = x; this.y = y;    this.itemNum = x.Length;}/// <summary>/// 獲得某個橫座標組應的Y座標值/// </summary>/// <param name="xValue">x座標值</param>/// <returns></returns>public double GetValue(int xValue){    //用於累乘數組始末下標    int start, end;    //傳回值    double value = 0.0;    //如果初始的離散點為空白, 返回0    if (itemNum < 1) { return value; }    //如果初始的離散點只有1個, 返回該點對應的Y值    if (itemNum == 1) { value = y[0]; return value; }    //如果初始的離散點只有2個, 進行線性插值並返回插值    if (itemNum == 2)    {        value = (y[0] * (xValue - x[1]) - y[1] * (xValue - x[0])) / (x[0] - x[1]);        return value;    }    //如果插值點小於第一個點X座標, 取數組前3個點做插值    if (xValue <= x[1]) { start = 0; end = 2; }    //如果插值點大於等於最後一個點X座標, 取數組最後3個點做插值    else if (xValue >= x[itemNum - 2]) { start = itemNum - 3; end = itemNum - 1; }    //除了上述的一些特殊情況, 通常情況如下    else    {        start = 1; end = itemNum;        int temp;        //使用二分法決定選擇哪三個點做插值        while ((end - start) != 1)        {            temp = (start + end) / 2;            if (xValue < x[temp - 1])                end = temp;            else                start = temp;        }        start--; end--;        //看插值點跟哪個點比較靠近        if (Math.Abs(xValue - x[start]) < Math.Abs(xValue - x[end]))            start--;        else            end++;    }    //這時已經確定了取哪三個點做插值, 第一個點為x[start]    double valueTemp;    //注意是二次的插值公式    for (int i = start; i <= end; i++)    {        valueTemp = 1.0;        for (int j = start; j <= end; j++)            if (j != i)                valueTemp *= (double)(xValue - x[j]) / (double)(x[i] - x[j]);        value += valueTemp * y[i];    }    return value;}

        等時間距擷取值的問題就這樣解決了, 但要注意這是二次插值, 也就是擬合的是二次及二次方程以下的函數.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.