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. 序列化的JavaScript

    下载 序列化的JavaScript序列化的JavaScript 将JavaScript序列化为包含正则表达式.日期和函数的JSON超集. 概述 这个包中的代码最初是作为表示状态的内部模块.为了扩展它的 ...

  2. [KMP]字符串匹配算法

    算法介绍: KMP是一种用来处理字符串匹配问题的算法,给你两个字符串A.B,让你回答B是否为A的子串,或者A中有多少子串等于B. 这题最暴力的做法是:枚举A中与B相等的子串的左端点,再判断是否与B相等 ...

  3. Springcloud技术分享

    Springcloud技术分享 Spring Cloud 是一套完整的微服务解决方案,基于 Spring Boot 框架,准确的说,它不是一个框架,而是一个大的容器,它将市面上较好的微服务框架集成进来 ...

  4. 多测师讲解ui自动化框架设计思想_高级讲师肖sir

    UI自动化框架:UI自动化框架可以分为8个模块,conf.data.public.pageobject.testcase.runner.report.log.conf是用来储存系统环境.数据库.邮件的 ...

  5. 多测师讲解rf--定位元素--高级讲师肖sir

    注意点: 注意点: rfbug:rf 点击勾选一个运行就运行两个出现用例执行 注释快捷键: 改字体大小: 快捷键:显示关键字信息 (ctrl+鼠标悬浮) 注解不能空格在注解 未保存提示 定位方法 : ...

  6. 【Azure Redis 缓存 Azure Cache For Redis】Redis性能问题,发现Server Load非常的高,导致正常连接/操作不成功

    问题描述 在正常使用Azure Redis的服务中,突然发现Redis 的CPU达到了100%, 正常的使用中发现性能问题严重.从Redis的门户图表中,观察到CPU, Connection,Lent ...

  7. 微信小程序的账号找回。

    之前注册过微信小程序,好久没用了,马上要开发微信小程序了,我今天登陆了一下突然发现 然后点击账号找回,按照流程同意点击下一步,到第二部时要输入搜索框里的提示. 这时的我早已忘了,百度搜了一下如何找回原 ...

  8. No compatible servers were found,You'll need to cancel this wizard and install one!

    原文链接:https://www.jianshu.com/p/a11f93fb16ce 问题原因 笔记本重装的windows系统,重新安装mysql的时候,显示错误,看了一下缺失服务,实际上可能是缺少 ...

  9. A. Cubes Sorting 解析(思維)

    Codeforce 1420 A. Cubes Sorting 解析(思維) 今天我們來看看CF1420 題目連結 題目 給一個數列\(a\),求能不能在不超過\(\frac{n(n-1)}{2}-1 ...

  10. SpringBoot连接多数据源(HBASE,KUDU,ORACLE集成和开发库)

    前提:1.连接hadoop需要本地安装 winutils.exe 并在程序指定,不然程序会报错  IOException: HADOOP_HOME or hadoop.home.dir are not ...