一直想把这几个插值公式用代码实现一下,今天闲着没事,尝试尝试。

先从最简单的拉格朗日插值开始!关于拉格朗日插值公式的基础知识就不赘述,百度上一搜一大堆。

基本思路是首先从文件读入给出的样本点,根据输入的插值次数和想要预测的点的x选择合适的样本点区间,最后计算基函数得到结果。直接看代码!(注:这里说样本点不是很准确,实在词穷找不到一个更好的描述。。。)

str2double

一个小问题就是怎样将python中的str类型转换成float类型,毕竟我们给出的样本点不一定总是整数,而且也需要做一些容错处理,比如多个+、多个-等等,也应该能识别为正确的数。所以实现了一个str2double方法。

import re
def str2double(str_num):
pattern = re.compile(r'^((\+*)|(\-*))?(\d+)(.(\d+))?$')
m = pattern.match(str_num)
if m is None:
return m
else:
sign = 1 if str_num[0] == '+' or '0' <= str_num[0] <= '9' else -1
num = re.sub(r'(\++)|(\-+)', "", m.group(0))
matchObj = re.match(r'^\d+$', num)
if matchObj is not None:
num = sign * int(matchObj.group(0))
else:
matchObj = re.match(r'^(\d+).(\d+)$', num)
if matchObj is not None:
integer = int(matchObj.group(1))
fraction = int(matchObj.group(2)) * pow(10, -1*(len(matchObj.group(2))))
num = sign * (integer + fraction)
return num

我使用了正则表达式来实现,pattern = re.compile(r'^((\+*)|(\-*))?(\d+)(.(\d+))?$')可以匹配我上面提到的所有类型的整数和浮点数,之后进行匹配,匹配成功,如果是整数,直接return整数部分,这个用(int)强制转换即可;如果是浮点数,那么用(\d+)这个正则表达式再次匹配,分别得到整数部分和小数部分,整数部分的处理和上面类似,小数部分则用乘以pow(10, -小数位数)得到,之后直接相加即可。这里为了支持多个+或者-,使用re.sub方法将符号去掉,所以就需要用sign来记录数字的正负,在最后return时乘上sign即可。

binary_search

def binary_search(point_set, n, x):
first = 0
length = len(point_set)
last = length
while first < last:
mid = (first + last) // 2
if point_set[mid][0] < x:
first = mid + 1
elif point_set[mid][0] == x:
return mid
else:
last = mid
last = last if last != length else last-1 head = last - 1
tail = last
while n > 0:
if head != -1:
n -= 1
head -= 1
if tail != length:
n -= 1
tail += 1
return [head+1, tail-1] if n == 0 else [head+1, tail-2]

这里point_set是全部样本点的集合,n是输入的插值次数,x是输入的预测点。返回合适的插值区间,即尽可能地把x包在里面。

因为要根据输入得到合适的插值区间,所以就涉及查找方面的知识。这里使用了二分查找,先对样本点集合point_set进行排序(升序),找到第一个大于需要预测点的样本点,在它的两侧扩展区间,直到满足插值次数要求。这里我的实现有些问题,可能会出现n=-1因为tail多加了一次,就在while循环外又进行了一次判断,n=-1tail-2,这个实现的确不好,可能还会有bug。。。

最后,剩下的内容比较好理解,直接放上全部代码。

import re
import matplotlib.pyplot as plt
import numpy as np def str2double(str_num):
pattern = re.compile(r'^((\+*)|(\-*))?(\d+)(.(\d+))?$')
m = pattern.match(str_num)
if m is None:
return m
else:
sign = 1 if str_num[0] == '+' or '0' <= str_num[0] <= '9' else -1
num = re.sub(r'(\++)|(\-+)', "", m.group(0))
matchObj = re.match(r'^\d+$', num)
if matchObj is not None:
num = sign * int(matchObj.group(0))
else:
matchObj = re.match(r'^(\d+).(\d+)$', num)
if matchObj is not None:
integer = int(matchObj.group(1))
fraction = int(matchObj.group(2)) * pow(10, -1*(len(matchObj.group(2))))
num = sign * (integer + fraction)
return num def preprocess():
f = open("input.txt", "r")
lines = f.readlines()
lines = [line.strip('\n') for line in lines]
point_set = list()
for line in lines:
point = list(filter(None, line.split(" ")))
point = [str2double(pos) for pos in point]
point_set.append(point)
return point_set def lagrangeFit(point_set, x):
res = 0
for i in range(len(point_set)):
L = 1
for j in range(len(point_set)):
if i == j:
continue
else:
L = L * (x - point_set[j][0]) / (point_set[i][0] - point_set[j][0])
L = L * point_set[i][1]
res += L
return res def showbasis(point_set):
print("Lagrange Basis Function:\n")
for i in range(len(point_set)):
top = ""
buttom = ""
for j in range(len(point_set)):
if i == j:
continue
else:
top += "(x-{})".format(point_set[j][0])
buttom += "({}-{})".format(point_set[i][0], point_set[j][0])
print("Basis function{}:".format(i))
print("\t\t{}".format(top))
print("\t\t{}".format(buttom)) def binary_search(point_set, n, x):
first = 0
length = len(point_set)
last = length
while first < last:
mid = (first + last) // 2
if point_set[mid][0] < x:
first = mid + 1
elif point_set[mid][0] == x:
return mid
else:
last = mid
last = last if last != length else last-1 head = last - 1
tail = last
while n > 0:
if head != -1:
n -= 1
head -= 1
if tail != length:
n -= 1
tail += 1
return [head+1, tail-1] if n == 0 else [head+1, tail-2] if __name__ == '__main__':
pred_x = input("Predict x:")
pred_x = float(pred_x)
n = input("Interpolation times:")
n = int(n)
point_set = preprocess()
point_set = sorted(point_set, key=lambda a: a[0])
span = binary_search(point_set, n+1, pred_x)
print("Chosen points: {}".format(point_set[span[0]:span[1]+1]))
showbasis(point_set[span[0]:span[1]+1]) X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
S = np.sin(X)
L = [lagrangeFit(point_set, x) for x in X]
L1 = [lagrangeFit(point_set[span[0]:span[1]+1], x) for x in X] plt.figure(figsize=(8, 4))
plt.plot(X, S, label="$sin(x)$", color="red", linewidth=2)
plt.plot(X, L, label="$LagrangeFit-all$", color="blue", linewidth=2)
plt.plot(X, L1, label="$LagrangeFit-special$", color="green", linewidth=2)
plt.xlabel('x')
plt.ylabel('y')
plt.title("$sin(x)$ and Lagrange Fit")
plt.legend()
plt.show()

About Input

使用了input.txt进行样本点读入,每一行一个点,中间有一个空格。

结果

感觉挺好玩的hhh,过几天试试牛顿插值!掰掰!

【数值分析】Python实现Lagrange插值的更多相关文章

  1. Python实现Newton和lagrange插值

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

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

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

  3. Python数值计算之插值曲线拟合-01

        3 插值与曲线拟合 Interpolation and Curve Fitting 给定n+1个数据点(xi,yi), i = 0,1,2,…,n,评估y(x). 3.1 介绍(introdu ...

  4. Note -「Lagrange 插值」学习笔记

    目录 问题引入 思考 Lagrange 插值法 插值过程 代码实现 实际应用 「洛谷 P4781」「模板」拉格朗日插值 「洛谷 P4463」calc 题意简述 数据规模 Solution Step 1 ...

  5. Lagrange插值C++程序

    输入:插值节点数组.插值节点处的函数值数组,待求点 输出:函数值 代码如下:把printf的注释取消掉,能打印出中间计算过程,包括Lagrange多项式的求解,多项式每一项等等(代码多次修改,这些pr ...

  6. Python SciPy库——插值与拟合

    插值与拟合 原文链接:https://zhuanlan.zhihu.com/p/28149195 1.最小二乘拟合 实例1 # -*- coding: utf-8 -*- import numpy a ...

  7. 数值计算方法实验之Lagrange 多项式插值 (Python 代码)

    一.实验目的 在已知f(x),x∈[a,b]的表达式,但函数值不便计算,或不知f(x),x∈[a,b]而又需要给出其在[a,b]上的值时,按插值原则f(xi)= yi(i= 0,1…….,n)求出简单 ...

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

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

  9. OpenCASCADE Interpolation - Lagrange

    OpenCASCADE Interpolation - Lagrange eryar@163.com Abstract. Power basis polynomial is the most simp ...

随机推荐

  1. 手写DAO框架(七)-如何保证连接可用

    版权声明:本文为博客园博主「水木桶」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明.原文链接:https://www.cnblogs.com/shuimutong/p ...

  2. spring boot 集成 sitemesh

    一.Sitemesh简介 Sitemesh是由一个基于Web页面布局.装饰及与现存Web应用整合的框架,是一个装饰器.它能帮助我们在由大量页面工程的项目中创建一致的页面布局和外观,如一致的导航条.一致 ...

  3. UAVCAN DSDL介绍

    原文:http://uavcan.org/Specification/3._Data_structure_description_language/ DSDL:Data structure descr ...

  4. Python学习笔记-数字,列表,元祖,切片,循环

    数字 1,加减乘除:+,-,*,/ 2,平方:** 3,立方:**3 4,字符串转换:str(数字) 5,浮点数:带小数点  0.2 Python编程建议 import this >>&g ...

  5. 后端接收json数据交互

    学习记录,后端接收json数据几种方式 1.直接接收或者通过HttpServletRequest接收 public void test(String userid, HttpServletReques ...

  6. Shell: sh,bash,csh,tcsh等shell的区别(转)

    转载自:http://zhidao.baidu.com/question/493376840.html, http://blog.sina.com.cn/s/blog_71261a2d0100wmbj ...

  7. Github 上 36 个最实用的 Vue 开源库

    任何一个开发者,都是十分喜欢使用开源软件包的.因为它使开发工作变得更快速.高效.容易.如果没有开源软件包,开发工作将变得疲惫不堪,不断的重复造轮子! 下面整理了 Github 上 36 个实用的 Vu ...

  8. 日常bug(1)

    今天在写写代码的时候,前端找我,说我写的一个接口有可能有问题.导致前端的数据不能正常显示,我去看了一下,确实不能正常显示.问题的原因是本来前端循环遍历一个json里的数组,但是接下来的数据变成对象了. ...

  9. linux查看redis安装目录

    1.在redis下查看安装目录 如果命令 which 和whereis 都找不到安装目录,可使用以下办法 ps -ef|grep redis 得到了进程号 xxxx 然后 ls -l /proc/xx ...

  10. Integer面试连环炮以及源码分析

    场景:   昨天有位朋友去面试,我问他面试问了哪些问题,其中问了Integer相关的问题,以下就是面试官问的问题,还有一些是我对此做了扩展. 问:两个new Integer 128相等吗? 答:不.因 ...