拉盖尔插值算法,我的实现有问题

时间:2012-11-14 17:09:48

标签: c++ math polynomial-math

这是一个我一直苦苦挣扎一个星期的问题,只是为了在浪费时间之后放弃......

我应该找到以下Laguerre多项式的系数:

P0(x) = 1

P1(x) = 1 - x

Pn(x) = ((2n - 1 - x) / n) * P(n-1) - ((n - 1) / n) * P(n-2)

我相信我的实现中存在错误,因为由于某种原因,我得到的系数似乎太大了。这是该程序生成的输出:

a1 = -190.234
a2 = -295.833
a3 = 378.283
a4 = -939.537
a5 = 774.861
a6 = -400.612

代码描述(如下所示):

如果你将代码向下滚动到我声明数组的部分,你会发现给定的x和y。

函数多项式只是用某个x的所述多项式的值填充数组。这是一个递归函数。我相信它运作良好,因为我检查了输出值。

高斯函数通过对输出数组执行高斯消元来找到系数。我认为这是问题的开始。我想知道,如果这段代码中有错误,或者我的非常结果的方法可能不好?我试图像那样验证它们:

-190.234 * 1.5 ^ 5 - 295.833 * 1.5 ^ 4 ... - 400.612 = -3017,817625 =/= 2

代码:

#include "stdafx.h"
#include <conio.h>
#include <iostream>
#include <iomanip>
#include <math.h>

using namespace std;

double polynomial(int i, int j, double **tab)
{
    double n = i;
    double **array = tab;
    double x = array[j][0];

    if (i == 0) {
        return 1;
    } else if (i == 1) {
        return 1 - x;
    } else {
        double minusone = polynomial(i - 1, j, array);
        double minustwo = polynomial(i - 2, j, array);
        double result = (((2.0 * n) - 1 - x) / n) * minusone - ((n - 1.0) / n) * minustwo;
        return result;
    }
}

int gauss(int n, double tab[6][7], double results[7])
{
    double multiplier, divider;

    for (int m = 0; m <= n; m++)
    {
        for (int i = m + 1; i <= n; i++)
        {
            multiplier = tab[i][m]; 
            divider = tab[m][m];

            if (divider == 0) {
                return 1;
            }

            for (int j = m; j <= n; j++)
            {
                if (i == n) {
                    break;
                }

                tab[i][j] = (tab[m][j] * multiplier / divider) - tab[i][j];
            }

            for (int j = m; j <= n; j++) {
                tab[i - 1][j] = tab[i - 1][j] / divider;
            }
        }
    }

    double s = 0;
    results[n - 1] = tab[n - 1][n];
    int y = 0;
    for (int i = n-2; i >= 0; i--)
    {
        s = 0;
        y++;
        for (int x = 0; x < n; x++)
        {
            s = s + (tab[i][n - 1 - x] * results[n-(x + 1)]); 

            if (y == x + 1) { 
                break;
            }
        }
        results[i] = tab[i][n] - s;
    }

}


int _tmain(int argc, _TCHAR* argv[])
{
    int num;
    double **array;

    array = new double*[5];
    for (int i = 0; i <= 5; i++)
    {
        array[i] = new double[2];
    }
                         //i         0      1       2       3       4       5
    array[0][0] = 1.5;  //xi         1.5    2       2.5     3.5     3.8     4.1
    array[0][1] = 2;    //yi         2      5       -1      0.5     3       7
    array[1][0] = 2;
    array[1][1] = 5;
    array[2][0] = 2.5;
    array[2][1] = -1;
    array[3][0] = 3.5;
    array[3][1] = 0.5;
    array[4][0] = 3.8;
    array[4][1] = 3;
    array[5][0] = 4.1;
    array[5][1] = 7;

    double W[6][7]; //n + 1

    for (int i = 0; i <= 5; i++)
    {
        for (int j = 0; j <= 5; j++)
        {
            W[i][j] = polynomial(j, i, array);
        }
        W[i][6] = array[i][1];
    }

    for (int i = 0; i <= 5; i++)
    {
        for (int j = 0; j <= 6; j++)
        {
            cout << W[i][j] << "\t";
        }
        cout << endl;
    }

    double results[6];
    gauss(6, W, results);

    for (int i = 0; i < 6; i++) {
        cout << "a" << i + 1 << " = " << results[i] << endl;
    }

    _getch();
    return 0;
}

2 个答案:

答案 0 :(得分:2)

我相信你对递归多项式生成的解释要么需要修改,要么对我来说有点过于聪明。

给定P [0] [5] = {1,0,0,0,0,...}; P [1] [5] = {1,-1,0,0,0,...};
然后P [2]是* P [0] +卷积(P [1],{c,d});
  其中a = - ((n - 1)/ n)    c =(2n-1)/ n且d = -1 / n

这可以推广:P [n] == a * P [n-2] + conv(P [n-1],{c,d}); 在每一步中都有一个带有(c + d * x)的多项式乘法,它将度数增加一(只有一个......)并加到P [n-1]乘以标量a。

然后很可能插值因子x在[0..1]范围内。

(卷积意味着你应该实现多项式乘法,幸运的是很容易......)

              [a,b,c,d]
                * [e,f]
        ------------------
           af,bf,cf,df  +
        ae,be,ce,de, 0  +
--------------------------
 (= coefficients of the final polynomial)

答案 1 :(得分:0)

P1(x) = x - 1的定义未按规定实施。您在计算中有1 - x

我没有再看了。