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实现的数据结构与算法之链表详解

    一.概述 链表(linked list)是一组数据项的集合,其中每个数据项都是一个节点的一部分,每个节点还包含指向下一个节点的链接.根据结构的不同,链表可以分为单向链表.单向循环链表.双向链表.双向循 ...

  2. C++中memset函数的用法

    转载:https://blog.csdn.net/qq_22122811/article/details/52738029 //复习数组的时候,第一次见到了memset,学之. memset:char ...

  3. 批处理中的删除命令:del

    转载:https://blog.csdn.net/playboy1/article/details/6869358 删除一个或数个文件.DEL [/P] [/F] [/S] [/Q] [/A[[:]a ...

  4. AE2018简单的编辑

    来源:https://jingyan.baidu.com/article/1876c8525cf522890a137651.html Ae 2018 怎样锁定图层,阻止对图层进行编辑? 听语音 原创 ...

  5. 【题解】 P2734 [USACO3.3]游戏 A Game

    \(\color{purple}{Link}\) \(\text{Solution:}\) 考虑区间\([l,r]\)的最优解.显然它可以由\([l+1,r]\)或\([l,r-1]\)转移而来.至此 ...

  6. Windows10系统下wsappx占用CPU资源过高?wsappx是什么?如何关闭wsappx进程?

    在Windows10系统开机的时候,wsappx进程占用的CPU资源非常高,导致电脑运行速度缓慢,那么我们如何关闭wsappx进程,让电脑加快运行速度呢?下面就一起来看一下操作的方法吧. [现象] 1 ...

  7. ansible-playbook-roles目录结构

    1. ansible-角色-roles目录结构       角色是基于已知文件结构自动加载某些vars_files,任务和处理程序的方法.按角色对内容进行分组还可以轻松与其他用户共享角色.      ...

  8. js 基础概念

    一 执行上下文 和 执行上下文栈 执行上下文:一段javascript代码执行前的准备工作 问题一:js引擎遇到怎样一段代码才会做"准备工作呢"? 可执行代码类型:全局代码.函数代 ...

  9. 《罗辑思维》试读:U盘化生存

    <罗辑思维>试读:U盘化生存 何为"U盘" 记得有一次我到一个大学去讲课,我随机做了一个调查.我说大四啦,咱们班同学谁找着工作了,一堆人举手.我又问都加入什么样的组织了 ...

  10. kinaba 安装踩坑: FATAL Error: [elasticsearch.url]: definition for this key is missing 转

     安装  https://www.jianshu.com/p/875457cb8da6   操作系统:Linux kibana 版本: 7.4.0 1. 在/etc/yum.repos.d/ 下新建 ...