问题:已知插值节点序列(xi, yi),i=01,2,…,n, 牛顿(Newton) 插值值多项
式Nn(x)计算的函数f(x)在点x0的近似值。
首先给出算法步骤:
(1)给已知条件(X0,y0),(X1,y1),(X2,y2),…,(Xn,yn)点进行对应的包装操作和编号处理
(2)根据已知条件(X0,y0),(X1,y1),(X2,y2),…,(Xn,yn)和要求解的x值计算差商:
2.1 当k=0时,N(x)=f(x0);
2.2 当k=1时,首先通过差商公式计算得到1阶差商
然后通过计算w(x)=(X-X0)…(X-Xn-1)
2.3 N(x)=N(x)+f[x0,x1]*(X-X0);
2.4 每次k自增1,重复2.2~2.3步骤操作,直到k=n为止
2.5 最后得出结果 N(x)即为x对应的值
源程序代码及运行结果截图
#include<iostream>
#include<vector>
#include<math.h>
#include<iomanip>
using namespace std;
struct Point
{
Point(float x, float y) {
this->x = x;
this->y = y;
}
Point() {
}
float x; //坐标的x轴
float y; //坐标的y轴
int k = -1; //给每个已知点进行编号,表示第k个点,k = 0,1,2....n
};
//存放已知点编号完成后的动态向量
vector<Point> *vec = NULL;
/*
@param points 要初始化的已知点数组
@param len 数组长度
*/
void init(Point points[], int len)
{
vec = new vector<Point>();
for (int i = 0; i < len; i++)
{
//给每个点进行编号处理
points[i].k = i;
//将每个点放入到向量集合中
vec->push_back(points[i]);
}
}
/*
@to do: 获取差商值
@param k 第k个点
@return float 返回结果
*/
float getDifferenceQuotient(int k) {
float result = 0; //差商值
vector<Point>::iterator it;
int count = 0;
for (it =vec->begin(); it!=vec->end(); it++)
{
float molecule = (*it).y; //差商的分子
float denominator = 1; //差商的分母
for (int i = 0; i <= k; i++)
{
if ((*it).k != i)
{
//开始利用差商公式累加求解
denominator = denominator*((*it).x - (*vec)[i].x);
}
}
//计算差商值
result += (molecule / denominator);
if (count == k)
{
break;
}
count++;
}
return result;
}
/*
@to do: 获取(x-x0)*(x-x1)*...*(x-Xk-2)的连乘结果
@param X 需要求解的x的值
@param k 需要连乘的次数
@return float 返回结果
*/
float getContinuousMultiplication(float x,int k) {
//用于保存连乘的结果
float result = 1.0f;
vector<Point>::iterator it;
//控制跳出循环的变量
int count = 0;
for (it = vec->begin(); it != vec->end(); it++)
{
//开始跳出循环
if (count == k)
{
break;
}
//累加进行求解 (X-X0)*...*(X-Xn-1)
result *= (x-(*it).x);
count++;
}
return result;
}
/*
@to do: 获取x0节点对应的朗格朗日函数值
@param X0 需要求解的x0的值
@return float 返回结果
*/
float getNewTonValue(float x0) {
vector<Point>::iterator it;
float result = 0; //最终结果
//用于控制k=0的情况和k>0的情况
int index = 0;
for (it = vec->begin(); it != vec->end(); it++)
{
if (index == 0)
{
//处理k=0时的情况
result += (*it).y;
}
else {
//处理k > 1时的情况
int k = (*it).k;
//获取差商值
float a = getDifferenceQuotient(k);
//获取连乘的值
float b = getContinuousMultiplication(x0,k);
//获取N(x)
result += a*b;
}
index++;
}
return result;
}
int main()
{
//测试数据
Point p1(0.4f, -0.9163f);
Point p2(0.5f, -0.6931f);
Point p3(0.6f, -0.5108f);
Point p4(0.7f, -0.3567f);
Point p5(0.8f, -0.2231f);
Point points[5] = { p1,p2,p3,p4,p5 };
init(points, 5);
float x = 0.54f;
float result = getNewTonValue(x);
cout << "通过牛顿插值公式计算后的数当x=" << x << "时其结果为:" << result << endl;
system("pause");
return 0;
}