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. Java知识系统回顾整理01基础06数组04增强型for循环

    增强型for循环在遍历一个数组的时候会更加快捷 一.增强型for循环 注:增强型for循环只能用来取值,却不能用来修改数组里的值 public class HelloWorld { public st ...

  2. 【题解】[USACO13FEB]Tractor S

    题目戳我 \(\text{Solution:}\) 好久没写啥\(dfs\)了,借这个题整理下细节. 观察到答案具有二分性,所以先求出其差的最大最小值,\(\log val\)的复杂度不成问题. 考虑 ...

  3. 【原创】经验分享:一个小小emoji尽然牵扯出来这么多东西?

    前言 之前也分享过很多工作中踩坑的经验: 一个线上问题的思考:Eureka注册中心集群如何实现客户端请求负载及故障转移? [原创]经验分享:一个Content-Length引发的血案(almost.. ...

  4. Java基础系列-RandomAccess

    原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755424.html Random是随机的意思,Access是访问的意思,合起来就是随机访问的意思. ...

  5. Python数据类型--列表(list)

    Python中列表对应的表示形式是"[]".列表中的元素可以是任何数据类型. 本文以List=[i for i in range(20)]为例进行论述:等价于List=[0, 1, ...

  6. hdfs的JAVA必会操作

    hdfs的必会操作 创建目录 //创建目录 public static void mkdir(String filePath) throws URISyntaxException, IOExcepti ...

  7. 发布MeteoInfo 1.2.8

    增加了对SYNOP数据的支持(功能从C#版移植过来).数据可以从这里下载:http://weather.cod.edu/digatmos/syn/SYNOP数据搞气象的人应该多少知道些,类似MICAP ...

  8. map的key排序

    java map的key排序吗 java为数据结构中的映射定义了一个接口java.util.Map,他实现了四个类,分别是:HashMap,HashTable,LinkedHashMapTreeMap ...

  9. MySQL锁详细讲解

    本文章向大家介绍MySQL锁详细讲解,包括数据库锁基本知识.表锁.表读锁.表写锁.行锁.MVCC.事务的隔离级别.悲观锁.乐观锁.间隙锁GAP.死锁等等,需要的朋友可以参考一下   锁的相关知识又跟存 ...

  10. spring boot:配置druid数据库连接池(开启sql防火墙/使用log4j2做异步日志/spring boot 2.3.2)

    一,druid数据库连接池的功能? 1,Druid是阿里巴巴开发的号称为监控而生的数据库连接池 它的优点包括: 可以监控数据库访问性能 SQL执行日志 SQL防火墙 2,druid的官方站: http ...