【数值分析】Python实现Lagrange插值
一直想把这几个插值公式用代码实现一下,今天闲着没事,尝试尝试。
先从最简单的拉格朗日插值开始!关于拉格朗日插值公式的基础知识就不赘述,百度上一搜一大堆。
基本思路是首先从文件读入给出的样本点,根据输入的插值次数和想要预测的点的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=-1
时tail-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插值的更多相关文章
- Python实现Newton和lagrange插值
一.介绍Newton和lagrange插值:给出一组数据进行Newton和lagrange插值,同时将结果用plot呈现出来1.首先是Lagrange插值:根据插值的方法,先对每次的结果求积,在对结果 ...
- 数值分析案例:Newton插值预测2019城市(Asian)温度、Crout求解城市等温性的因素系数
数值分析案例:Newton插值预测2019城市(Asian)温度.Crout求解城市等温性的因素系数 文章目录 数值分析案例:Newton插值预测2019城市(Asian)温度.Crout求解城市等温 ...
- Python数值计算之插值曲线拟合-01
3 插值与曲线拟合 Interpolation and Curve Fitting 给定n+1个数据点(xi,yi), i = 0,1,2,…,n,评估y(x). 3.1 介绍(introdu ...
- Note -「Lagrange 插值」学习笔记
目录 问题引入 思考 Lagrange 插值法 插值过程 代码实现 实际应用 「洛谷 P4781」「模板」拉格朗日插值 「洛谷 P4463」calc 题意简述 数据规模 Solution Step 1 ...
- Lagrange插值C++程序
输入:插值节点数组.插值节点处的函数值数组,待求点 输出:函数值 代码如下:把printf的注释取消掉,能打印出中间计算过程,包括Lagrange多项式的求解,多项式每一项等等(代码多次修改,这些pr ...
- Python SciPy库——插值与拟合
插值与拟合 原文链接:https://zhuanlan.zhihu.com/p/28149195 1.最小二乘拟合 实例1 # -*- coding: utf-8 -*- import numpy a ...
- 数值计算方法实验之Lagrange 多项式插值 (Python 代码)
一.实验目的 在已知f(x),x∈[a,b]的表达式,但函数值不便计算,或不知f(x),x∈[a,b]而又需要给出其在[a,b]上的值时,按插值原则f(xi)= yi(i= 0,1…….,n)求出简单 ...
- 转Python SciPy库——拟合与插值
1.最小二乘拟合 实例1 import numpy as np import matplotlib.pyplot as plt from scipy.optimize import leastsq p ...
- OpenCASCADE Interpolation - Lagrange
OpenCASCADE Interpolation - Lagrange eryar@163.com Abstract. Power basis polynomial is the most simp ...
随机推荐
- CSS揭秘(引言)
1.标准的制定过程 a 人员结构:W3C会员公司的成员.特邀专家.W3C工作人员 b 尽管“CSS3”非常流行,但它实际上并没有在任何规范中定义过.它实际上是指一个非正式的集合,包括CSS规范第三版再 ...
- 【Excel】【Salesforce】函数拓展
1.if 2.vlookup
- CentOS 7 - 修改时区为上海时区
1.查看时间各种状态: timedatectl Local time: 四 2014-12-25 10:52:10 CSTUniversal time: 四 2014-12-25 02:52:10 U ...
- 如何选择优秀的APS系统供应商?问自己这几个问题!
高级的计划和排程和生产排程软件的好处是巨大的.然而,生产排程软件不是商品,尚不能保证您选择的任何高级的计划和排程软件能满足您的所有需求. 那么,我们来谈谈如何选择适合你的公司最好的生产排程软件.这需要 ...
- day 06 预科
目录 if判断 if判断习题 for循环 for循环习题 微信机器人 if判断 # 一条狗朝你过来了,你会干吗? 判断: 如果狗是大长腿牵来的狗--->打招呼:如果是条疯狗,跑. # if:如果 ...
- GTID主从与传统主从复制
目录 1.主从复制 2.靠什么同步 3.pos与GTID的什么区别 4.GTID的工作原理 5.GTID参数配置 5.1 在主数据库里创建一个同步账号授权给从数据库使用 5.2 配置主数据库 5.3配 ...
- Echo团队Alpha冲刺随笔 - 第十天
项目冲刺情况 进展 对Web端和小程序端进行各项功能的测试 问题 bug无穷无尽 心得 debug使人秃头,希望明天能挑好 今日会议内容 黄少勇 今日进展 测试小程序,对发现的bug进行处理 存在问题 ...
- ZOJ - 2132:The Most Frequent Number(思维题)
pro:给定N个数的数组a[],其中一个数X的出现次数大于N/2,求X,空间很小. sol:不能用保存数组,考虑其他做法. 由于出现次数较多,我们维护一个栈,栈中的数字相同,所以我们记录栈的元素和个数 ...
- 2、Python的IDE之PyCharm的使用
一.Python集成开发环境-Pycharm介绍 PyCharm是一款功能强大的,用于编写复杂需要结构化的功能代码,下面介绍一下 在Windows下如何安装PyCharm . 操作系统:Windows ...
- StringTokenizer字符串分解器
示例: StringTokenizer st = new StringTokenizer(key, ",", false); while (st.hasMoreTokens()) ...