我更新了代码。 我想要做的是在指针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个点找出y(x)= cos(πx),x∈-1,1的拉格朗日多项式逼近 (x = -1,-0.5,0,0.5和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;
}
Here is an example of lagrange polynomial
答案 0 :(得分:6)
由于这似乎是家庭作业,我不打算给你一个详尽的答案,而是试着让你走上正确的轨道。
您正在做的是希望C ++为您做一些代数操作,并使用符号变量简化您的产品。如果没有很多努力,C ++就无法做到这一点。
您有两种选择:
希望这会给你一些如何开始的想法。
您的代码中仍然有一个未定义的表达式,因为您从未将任何值设置为y
。这会使prod*=(y-x[i])/(x[k]-x[i])
作为不返回有意义数据的表达式。 C ++只能使用数字,y
现在不是你的数字,但你认为它是符号。
如果要在代码中设置1
,则可以评估 lagrange近似值,例如值y=1
。这会给你(就我现在所见)正确的函数值,但没有函数本身的描述。
也许你应该先拿一支笔和一张纸,然后尝试将表达式写成精确的数学。尝试真正掌握您想要计算的内容。如果你那样做,也许你回到这里告诉我们你的想法。这应该可以帮助您了解那里发生了什么。
永远记住:C ++需要数字,而不是符号。每当你的纸上的表达式中有一个符号,你不知道你的价值时,你可以找到一种方法来计算已知值的值,或者你必须消除使用这个符号计算的需要。
P.S。:在multiple讨论区中同时发布相同问题并不是一种好的方式......
现在您在y = 0.3处评估函数。如果要评估多项式,这是要采用的方法。但是,正如您所说,您需要多项式的所有系数。
同样,我仍然觉得你不理解问题背后的数学。也许我会给你一个小例子。我将使用维基百科文章中使用的符号。
假设我们有k = 2且x = -1,1。此外,为了简单起见,我只需命名你的cos函数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中的商相互相乘。弄清楚这是如何完成的,你几乎完成了。
好的,让我们不那么模糊。
我们首先想要计算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并与函数相乘。那是你要弄明白的。 (请注意,我在那里做了很多低效的工作,但我希望这有助于你更好地理解细节。)
希望这能让您了解如何继续。
答案 1 :(得分: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
中系列表示的系数。
答案 2 :(得分: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(π)?