2

我更新了代码。我想要做的是将每个拉格朗日的系数值保存在指针 d 中。(例如,对于 L1(x) d[0] 将是 "x-x2/x1-x2" ,d 1将是 (x-x2/ x1-x2)*(x-x3/x1-x3) 等。

我的问题是

1)如何初始化 d(我做了 d[0]=(zx[i])/(x[k]-x[i]) 但我认为“d[0]”不正确

2)如何初始化L_coeff。(我正在使用 L_coeff=new double[0] 但不确定它是否正确。

练习是:使用 5 个点(x = -1、-0.5、0、0.5 和 1)求 y(x)=cos(π x), x ∈−1,1 的拉格朗日多项式逼近。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>

using namespace std;

const double pi=3.14159265358979323846264338327950288;

// my function
double f(double x){

return (cos(pi*x));

}


//function to compute lagrange polynomial
double lagrange_polynomial(int N,double *x){
//N = degree of polynomial

double z,y;
double *L_coeff=new double [0];//L_coefficients of every Lagrange L_coefficient
double *d;//hold the polynomials values for every Lagrange coefficient
int k,i;
//computations for finding lagrange polynomial
//double sum=0;

for (k=0;k<N+1;k++){
        for ( i=0;i<N+1;i++){
            if (i==0) continue;
            d[0]=(z-x[i])/(x[k]-x[i]);//initialization
            if (i==k) L_coeff[k]=1.0;
            else if (i!=k){
            L_coeff[k]*=d[i];

                      }

           }

cout <<"\nL("<<k<<") = "<<d[i]<<"\t\t\tf(x)= "<<f(x[k])<<endl;
}

}

int main()
{

    double deg,result;
    double *x;


    cout <<"Give the degree of the polynomial :"<<endl;
    cin >>deg;

    for (int i=0;i<deg+1;i++){
    cout <<"\nGive the points of interpolation : "<<endl;
    cin >> x[i];
    }

    cout <<"\nThe Lagrange L_coefficients are: "<<endl;
    result=lagrange_polynomial(deg,x);



    return 0;
}

这是拉格朗日多项式的示例

这是我所做的解决方案

4

3 回答 3

6

由于这似乎是家庭作业,我不会给你一个详尽的答案,而是试着让你走上正确的轨道。

  • 您如何在计算机软件中表示多项式?您想要存档为符号表达式(如 3x^3+5x^2-4)的直观版本对于进一步计算非常不实用。
  • 多项式是通过保存(和输出)它的系数来完全定义的。

您在上面所做的是希望 C++ 为您做一些代数操作并使用符号变量简化您的产品。这不是 C++ 不费力气就能做到的。

你有两个选择:

  • 使用可以进行符号操作的适当计算机代数系统(Maple 或 Mathematica 是一些示例)
  • 如果您必须使用 C++,则必须多考虑如何计算多项式的单个系数。您的程序输出只能是数字列表(当然,您可以根据符号表达式将其格式化为漂亮的字符串)。

希望这能给你一些如何开始的想法。

编辑 1

您的代码中仍然有一个未定义的表达式,因为您从未将任何值设置为y. 这将作为一个表达式留下prod*=(y-x[i])/(x[k]-x[i]),不会返回有意义的数据。C++ 只能处理数字,y现在对你来说不是数字,但你认为它是符号。

如果您要在代码中设置,您可以评估拉格朗日近似值,比如 value 。这会给你(据我现在所见)正确的函数值,但没有函数本身的描述。1y=1

也许你应该先拿一支笔和一张纸,试着把表达式写成精确的数学。尝试真正掌握要计算的内容。如果你这样做了,也许你会回到这里告诉我们你的想法。这应该可以帮助您了解那里发生了什么。

永远记住:C++ 需要数字,而不是符号。每当您在纸上的表达式中有一个您不知道其值的符号时,您可以找到一种方法如何从已知值中计算该值,或者您必须消除使用该符号进行计算的需要。

PS:一次在多个讨论区发布相同的问题被认为是不好的风格......

编辑 2

现在您在点 y=0.3 处评估函数。如果您想评估多项式,这是要走的路。但是,正如您所说,您需要多项式的所有系数。

再一次,我仍然觉得你没有理解问题背后的数学原理。也许我会给你一个小例子。我将使用维基百科文章中使用的符号。

假设我们有 k=2 和 x=-1, 1。此外,为了简单起见,我只命名你的 cos-Function f。(没有乳胶,符号会变得相当难看......)然后拉格朗日多项式定义为

f(x_0) * l_0(x) + f(x_1)*l_1(x)

其中(通过再次象征性地进行简化)

l_0(x)= (x - x_1)/(x_0 - x_1) = -1/2 * (x-1) = -1/2 *x  + 1/2
l_1(x)= (x - x_0)/(x_1 - x_0) = 1/2 * (x+1)  = 1/2 * x  + 1/2

所以,你的拉格朗日多项式是

  f(x_0) * (-1/2 *x  + 1/2) + f(x_1) * 1/2 * x  + 1/2
= 1/2 * (f(x_1) - f(x_0)) * x     +     1/2 * (f(x_0) + f(x_1))

因此,您要计算的系数将是 1/2 * (f(x_1) - f(x_0)) 和 1/2 * (f(x_0) + f(x_1))。

你现在的任务是找到一种算法,可以进行我所做的简化,但不使用符号。如果您知道如何计算 l_j 的系数,那么您基本上就完成了,因为您只需将乘以 f 的相应值的那些相加即可。

因此,进一步细分,您必须找到一种方法,将 l_j 中的商逐个组件相乘。弄清楚这是如何完成的,你就快完成了。

编辑 3

好吧,让我们稍微模糊一点。

我们首先要计算 L_i(x)。这些只是线性函数的乘积。如前所述,我们必须将每个多项式表示为一个系数数组。为了更好的风格,我将使用std::vector这个数组来代替。然后,我们可以像这样定义保存 L_1(x) 系数的数据结构:

std::vector L1 = std::vector(5); 
// Lets assume our polynomial would then have the form 
// L1[0] + L2[1]*x^1 + L2[2]*x^2 + L2[3]*x^3 + L2[4]*x^4

现在我们想用值填充这个多项式。

// First we have start with the polynomial 1 (which is of degree 0)
// Therefore set L1 accordingly:
L1[0] = 1;
L1[1] = 0; L1[2] = 0; L1[3] = 0; L1[4] = 0;
// Of course you could do this more elegant (using std::vectors constructor, for example)
for (int i = 0; i < N+1; ++i) {
    if (i==0) continue;  /// For i=0, there will be no polynomial multiplication
    // Otherwise, we have to multiply L1 with the polynomial
    // (x - x[i]) / (x[0] - x[i])
    // First, note that (x[0] - x[i]) ist just a scalar; we will save it:
    double c = (x[0] - x[i]);
    // Now we multiply L_1 first with (x-x[1]). How does this multiplication change our 
    // coefficients? Easy enough: The coefficient of x^1 for example is just
    // L1[0] - L1[1] * x[1]. Other coefficients are done similary. Futhermore, we have
    // to divide by c, which leaves our coefficient as
    // (L1[0] - L1[1] * x[1])/c. Let's apply this to the vector:
    L1[4] = (L1[3] - L1[4] * x[1])/c;
    L1[3] = (L1[2] - L1[3] * x[1])/c;
    L1[2] = (L1[1] - L1[2] * x[1])/c;
    L1[1] = (L1[0] - L1[1] * x[1])/c;
    L1[0] = (      - L1[0] * x[1])/c; 
    // There we are, polynomial updated.
}

当然,这必须对所有 L_i 进行。然后,必须将 L_i 与函数相加并相乘。那是你自己想办法。(请注意,我在那里做了很多低效的东西,但我希望这能帮助你更好地理解细节。)

希望这能让您了解如何进行。

于 2011-07-09T12:51:29.163 回答
1

该变量y实际上不是代码中的变量,而是代表P(y)拉格朗日近似值的变量。

因此,您必须理解计算prod*=(y-x[i])/(x[k]-x[i]),而sum+=prod*f不是直接理解,而是象征性理解。

您可以通过一系列定义近似值来解决这个问题

c[0] * y^0 + c[1] * y^1 + ...

由代码中的数组表示c[]。然后你可以例如实现乘法

d = c * (y-x[i])/(x[k]-x[i])

像系数一样

d[i] = -c[i]*x[i]/(x[k]-x[i]) + c[i-1]/(x[k]-x[i])

与您必须在组件基础上实现添加和分配的方式相同。

结果将始终是您在变量中的系列表示的系数y

于 2011-07-09T12:52:46.980 回答
0

除了现有的回复之外,只有几条评论。

练习是:使用 5 个点(x = -1、-0.5、0、0.5 和 1)求 y(x)=cos(π x)、x ∈ [-1,1] 的拉格朗日多项式逼近。

您要做的第一件事main()是询问多项式的次数。你不应该那样做。多项式的次数完全由控制点的数量指定。在这种情况下,您应该构建通过五个点 (x i , cos(π x i ))的唯一四阶拉格朗日多项式,其中 x i值是这五个指定点。

const double pi=3.1415;

这个值不适合浮点数,更不用说双精度数了。你应该使用类似的东西const double pi=3.14159265358979323846264338327950288;

或者更好的是,根本不要使用pi。您应该确切地知道与给定 x 值相对应的 y 值是什么。什么是 cos(-π)、cos(-π/2)、cos(0)、cos(π/2) 和 cos(π)?

于 2011-07-12T13:59:55.623 回答