Newton(牛顿)插值法具有递推性,这决定其性能要好于Lagrange(拉格朗日)插值法。其重点在于差商(Divided Difference)表的求解。

步骤1. 求解差商表,这里采用非递归法(看着挺复杂挺乱,这里就要自己动笔推一推了,闲了补上其思路),这样,其返回的数组(指针)就是差商表了,

/*
* 根据插值节点及其函数值获得差商表
* 根据公式非递归地求解差商表
* x: 插值节点数组
* y: 插值节点处的函数值数组
* lenX: 插值节点的个数
* return: double类型数组
*/
double * getDividedDifferenceTable(double x[], double y[], int lenX) {
double *result = new double[lenX*(lenX - 1) / 2];
for (int i = 0; i < lenX - 1; i++) {
result[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]);
}
int step = lenX - 1; // 增加步长
int yindex = lenX - 1; // 分子的基准值,线性减速递增
int xgap = 2; // 分母的间距,每次+1
int xstep = 2;
while (step >= 1) {
for (int i = 0; i < step - 1; i++) {
result[yindex + i] = (result[yindex - step + i + 1] - result[yindex - step + i]) / (x[xstep + i] - x[xstep + i - xgap]);
}
yindex += (step - 1);
xstep++;
step--;
xgap++;
} return result;
}

步骤 2. 取得差商表每一列的第一个作为基函数的系数

/**
* 从差商表中获取一定阶数的某个差商
* dd: 差商表
* len: 差商表的长度
* rank: 所取差商的阶数
* index: rank阶差商的第index个差商
* return: 返回double类型所求差商
*/
double getDividedDifference(double dd[], int len, int rank, int index) {
// 根据差商表的长度求解差商的最高阶数
// 由于差商表是三角形的,因此有规律可循,解方程即可
int rankNum = (int)(0.5 + sqrt(2 * len + 0.25) - 1);
printf("%d 阶差商 \n", rank);
int pos = 0;
int r = 1;
// 根据n+(n+1)+...+(n-rank)求得rank阶差商在差商表数组中的索引
while (rank > 1)
{
// printf("geting dd's index, waiting...\n");
pos += rankNum;
rank--;
rankNum--;
}
pos += index; // 然后加上偏移量,意为rank阶差商的第index个差商 return dd[pos];
}

步骤3. Newton 插值主流程

/*
* Newton Interpolating 牛顿插值主要代码
* x: 插值节点数组
* y: 插值节点处的函数值数组
* lenX: 插值节点个数(数组x的长度)
* newX: 待求节点的数组
* lennx: 待求节点的个数(数组lenX的长度)
*/
double *newtonInterpolation(double x[], double y[], int lenX, double newX[], int lennx) {
// 计算差商表
double *dividedDifferences = getDividedDifferenceTable(x, y, lenX);
//
double *result = new double[lennx]; // 求差商表长度
int ddlength = 0;
for (int i = 1; i < lenX; i++)
{
ddlength += i;
}
// 打印差商表信息
printf("=======================差商表的信息=======================\n");
printf("差商个数有:%d, 待插值节点个数:%d\n =======================差商表=======================", ddlength, lennx);
int ifnextrow = 0; // 控制打印换行
for (int i = 0; i < ddlength; i++) {
if (ifnextrow == (i)*(i + 1) / 2)
printf("\n");
printf("%lf, ", dividedDifferences[i]);
ifnextrow++;
}
printf("\n");
// 计算Newton Interpolating 插值
double ddi = 0;
double coef = 1;
for (int i = 0; i < lennx; i += 2) {
coef = (double)1;
result[i] = y[i];
printf("=============打印计算过程=============\n");
for (int j = 1; j < lenX -1; j++) {
coef *= (newX[i] - x[j - 1]);
ddi = getDividedDifference(dividedDifferences, ddlength, j, 0);
printf("取得差商: %lf\n", ddi);
result[i] = result[i] + coef * ddi;
printf("计算result[%d] + %lf * %lf", i, coef, ddi);
printf("获得结果result %d: %lf\n", i, result[i]);
}
printf("result[%d] = %lf\n", i, result[i]); // =======================选做题:求误差==========================
printf("求解截断误差 所需差商:%lf\n", getDividedDifference(dividedDifferences, ddlength, lenX-1, 0));
// printf("求解截断误差 所需多项式:%lf\n", coef);
printf("求解截断误差 所需多项式的最后一项:%lf - %lf\n", newX[i] , x[lenX - 2]);
result[i + 1] = getDividedDifference(dividedDifferences, ddlength, lenX - 1, 0)*coef*(newX[i] - x[lenX - 2]);
// ===============================================================
}
if (dividedDifferences) {
delete[] dividedDifferences;
}
return result;
}

步骤4. 主函数示例

int main()
{
std::cout << "Hello World!\n";
printf("Newton插值!\n");
double x[] = {0.40, 0.55, 0.65, 0.80, 0.90, 1.05};
//double x[] = { 1.5, 1.6, 1.7 };
int lenX = sizeof(x) / sizeof(x[0]);
double y[] = {0.41075, 0.57815, 0.69675, 0.88811, 1.02652, 1.25382};
//double y[] = { 0.99749, 0.99957, 0.99166 };
double newx[] = {0.596};
//double newx[] = { 1.609 };
// 计算牛顿插值结果和截断误差
double *result = newtonInterpolation(x, y, lenX, newx, 1);
printf("=====================最终结果=====================\n");
printf("求得sin(1.609)的近似值为:%lf\n", *result);
printf("截断误差:%.10lf\n", *(result + 1));
if (result) {
delete[] result;
}
return 0;
}

Newton插值的C++实现的更多相关文章

  1. 数值分析案例:Newton插值预测2019城市(Asian)温度、Crout求解城市等温性的因素系数

    数值分析案例:Newton插值预测2019城市(Asian)温度.Crout求解城市等温性的因素系数 文章目录 数值分析案例:Newton插值预测2019城市(Asian)温度.Crout求解城市等温 ...

  2. 等距结点下的Newton插值多项式系数计算(向前差分)

    插值多项式的牛顿法 1.为何需要牛顿法? ​ 使用Lagrange插值法不具备继承性.当求好经过\(({x_0},{y_0})-({x_n},{y_n})\)共n+1个点的插值曲线时候,如果再增加一个 ...

  3. Python实现Newton和lagrange插值

    一.介绍Newton和lagrange插值:给出一组数据进行Newton和lagrange插值,同时将结果用plot呈现出来1.首先是Lagrange插值:根据插值的方法,先对每次的结果求积,在对结果 ...

  4. 插值方法 - Newton向前向后等距插值

    通常我们在求插值节点的开头部分插值点附近函数值时,使用Newton前插公式:求插值节点的末尾部分插值点附近函数值时,使用Newton后插公式. 代码: 1 # -*- coding: utf-8 -* ...

  5. scipy插值与拟合

    原文链接:https://zhuanlan.zhihu.com/p/28149195 1.最小二乘拟合 实例1 import numpy as np import matplotlib.pyplot ...

  6. 拉格朗日插值和牛顿插值 matlab

    1. 已知函数在下列各点的值为   0.2 0.4 0.6 0.8 1.0   0.98 0.92 0.81 0.64 0.38 用插值法对数据进行拟合,要求给出Lagrange插值多项式和Newto ...

  7. 转Python SciPy库——拟合与插值

    1.最小二乘拟合 实例1 import numpy as np import matplotlib.pyplot as plt from scipy.optimize import leastsq p ...

  8. 多项式函数插值:全域多项式插值(一)单项式基插值、拉格朗日插值、牛顿插值 [MATLAB]

    全域多项式插值指的是在整个插值区域内形成一个多项式函数作为插值函数.关于多项式插值的基本知识,见“计算基本理论”. 在单项式基插值和牛顿插值形成的表达式中,求该表达式在某一点处的值使用的Horner嵌 ...

  9. 插值方法 - Newton多项式(非等距节点)

    不多话.Nowton插值多项式(非等距节点)代码: 1 # -*- coding: utf-8 -*- 2 """ 3 Created on Wed Mar 25 15: ...

随机推荐

  1. Python 为什么不支持 switch 语句?

    本文出自"Python为什么"系列,请查看全部文章 在这篇文章里,我们会聊一聊为什么 Python 决定不支持 switch 语句. 为什么想要聊这个话题呢? 主要是因为 swit ...

  2. C++有子对象的派生类的构造函数

    转载:https://blog.csdn.net/qq1169091731/article/details/50934588?utm_source=blogxgwz6 类的数据成员不但可以是标准型(如 ...

  3. python opencv 读取图片 返回图片某像素点的b,g,r值

    转载:https://blog.csdn.net/weixin_41799483/article/details/80884682 #coding=utf-8   #读取图片 返回图片某像素点的b,g ...

  4. 【题解】[SDOI2017]数字表格

    Link #include<bits/stdc++.h> using namespace std; #define int long long const int MAXN=1e6; in ...

  5. 从零开始学python之Python安装和环境配置

    Python 3适用于Windows,Mac OS和大多数Linux操作系统.即使Python 2目前可用于许多其他操作系统,有部分系统Python 3还没有提供支持或者支持了但被它们在系统上删除了, ...

  6. mongoose 查询数据属性为数组,且包含某个值的方法

    mongoose在创建schema的时候有些属性需要设置为数组类型,比如商品图片.商品标签.不同尺寸.价格等. 那么怎么查询具有某个标签的商品了,下面记录一下两种情况: 查询具有'vue'标签的文章 ...

  7. centos7.5安装gcc7.2.0

    参考https://www.cnblogs.com/lazyInsects/p/9778910.html cd /usr/src wget https://mirrors.tuna.tsinghua. ...

  8. ASP.Net Core3.1 生成二维码填坑

    ASP.Net Core3.1 使用QrCode生成二维码 部署到Linux报错 The type initializer for 'System.DrawingCore.GDIPlus' threw ...

  9. 题解:[COCI2011-2012#5] BLOKOVI

    题解:[COCI2011-2012#5] BLOKOVI Description PDF : https://hsin.hr/coci/archive/2011_2012/contest5_tasks ...

  10. go 结构体初始化

    package main import "fmt" type Dog struct { Name string } func TestStruct() { // 方式1 //var ...