埃特金算法虽然具有承袭性,但其算式时递推型的,不便于理论上的分析。所以采用具有承袭性的显式的牛顿插值公式是不错的选择。
见下图:
按照差商的表达式,如果调换两个节点的顺序,只是意味着改变式子求和的顺序,其值不变。
例:已知节点 (0,1)(2,3)(3,2)(5,5) ,构造三次Newton 插值多项式,当 x = 2.5 时,计算 Newton 多项式插值结果。
解:由前面计算的差商值,我们很容易写出三次 Newton 插值多项式如下:
- 运行示例:
- 源码:
#include<iostream>
using namespace std;
#define MAX 10
typedef struct Point //插值节点信息结构体
{
double x;
double y;
}point;
int main(void)
{
int n; //插值节点个数
double x;
point p[MAX]; //定义结构体数组
cout << "请输入插值节点的个数:";
cin >> n;
for (int i = 1; i <= n; i++) //将节点信息存入结构体数组
{
cout << "请输入第" << i << "个点的坐标:";
cin >> p[i].x;
cin >> p[i].y;
}
cout << "请输入x的值:"; //输入x提示
cin >> x;
double item, sum; //item为每一项的值,等于各阶差商与右半部分的乘积;sum为牛顿插值的最终解
sum = 0; //对每一项值累加,作为最终牛顿插值的解
for (int i = 1; i <= n; i++) //有n项,循环n次
{
double differenceCoefficient = 0; //对差商赋初值0
double right = 1; //对右半部分赋初值1
if (i == 1) //根据牛顿插值公式,第一项为f(x1)即0阶差商,直接继续求二阶差商
{
item = p[1].y;
sum += item;
continue;
}
//求右边部分即(x-x1),(x-x1)(x-x2)......
for (int j = 1; j < i; j++)
{
right *= (x - p[j].x);
}
double temp, leftSum; //temp表示分子与分母之商即各阶差商里面的一项;leftSum为左半部分之和即各阶差商里各项的值也即最终差商differenceCoefficient
double numerator; //分子
//赋初值
leftSum = 0;
//求左边部分leftSum即f(x1,x2),f(x1,x2,x3)......也即差商differenceCoefficient
for (int k = 1; k <= i; k++)
{
double denominator = 1; //每次循环赋分母初值为1
if (i == 1 && k == 1) //i=1时不处理,直接退出
{
leftSum = 1;
break;
}
numerator = p[k].y; //求差商过程中,里面每一项的分子
for (int m = 1; m <= i; m++)
{
if (m == k)
{
continue;
}
denominator *= (p[k].x - p[m].x); //累乘分母
}
temp = numerator / denominator; //求分子与分母之商,求得组成差商的每一项
leftSum += temp; //累加组成差商的每一项,最终结果为差商differenceCoefficient
}
differenceCoefficient = leftSum; //值赋给差商
item = differenceCoefficient * right; //求第i项的值,即牛顿插值公式中的每一项
sum += item; //累加的最终牛顿插值解
}
cout << "\n运用牛顿插值法求得f(x)=" << sum << endl;
return 0;
}