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

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

基本思路是首先从文件读入给出的样本点,根据输入的插值次数和想要预测的点的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. MySQL数据库之互联网常用分库分表方案

    一.数据库瓶颈 不管是IO瓶颈,还是CPU瓶颈,最终都会导致数据库的活跃连接数增加,进而逼近甚至达到数据库可承载活跃连接数的阈值.在业务Service来看就是,可用数据库连接少甚至无连接可用.接下来就 ...

  2. jquery实现弹出层完美居中效果

    代码如下: showDiv($("#pop"));function showDiv(obj){ $(obj).show(); center(obj); $(window).scro ...

  3. RTSP协议介绍 (转)

    1. 实 时流协议RTSP RTSP[3]协 议以客户服务器方式工作,它是一个多媒体播放控制协议,用来使用户在播放从因特网下载的实时数据时能够进行控制,如:暂停/继 续.后退.前进等.因此 RTSP ...

  4. python基础-模块(全是理论,没有代码)

    模块 概念:一系列功能的结合体.相当于模块包着一堆函数与代码.本质上是py文件. 来源: python内置的模块----→ python解释器的模块 第三方的模块 -----→ 其他人编写提供的 自定 ...

  5. union的使用

    将多条select语句的结果,合并到一起,称为联合查询 使用union关键字 场景: 获取数据的条件,出现逻辑冲突,或者很难在一个逻辑内表示,就可以拆成多个逻辑,分别实现,最后将结果合并到一起 sel ...

  6. 【HCIA Gauss】学习汇总-数据库管理(SQL语法 库表 索引操作)-5

    # 简单查询select * from table_reference # 创建表 create table TB(staff_id int primary key , course_name cha ...

  7. Python_类的继承与方法重写

    1.新建子类时,括号内要传入继承的父类名 2.super()方法:自动寻找当前类的父类,并调用父类的构造函数,初始化属性值 class Cup: #构造函数,初始化属性值 def __init__(s ...

  8. Python idle中lxml 解析HTML时中文乱码解决

    例: <html><p>中文</p></html> 读取代码: 代码HTML需要进行decode('utf-8') 编译: p=etree.HTML(u ...

  9. 深入理解JVM内存分配和常量池

    一.虚拟机的构成 虚拟结主要由运行时数据区.执行引擎.类加载器三者构成: 而我们所说的JVM内存模型指的就是运行时数据区,下面具体分析一下运行时数据区: 二.运行时数据区组成和各个区域的作用 我们看到 ...

  10. django-配置静态页面-celery/redis/nginx

    celery生成静态页面 celery_tasks/tasks.py # 生成静态首页 from django.template import loader, RequestContext # tem ...