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

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

基本思路是首先从文件读入给出的样本点,根据输入的插值次数和想要预测的点的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. 正则表达式修饰符 i、g、m、s、U、x、a、D、e 等。

    正则表达式中常用的模式修正符有i.g.m.s.U.x.a.D.e 等. 它们之间可以组合搭配使用. i 不区分(ignore)大小写: 例如: /abc/i 可以匹配 abc.aBC.Abc g 全局 ...

  2. C#操作mongodb(聚合函数)-分组找出每组的最大值

    public static void OnQuery_QXData(string DBName, string tablename,string layername)        {         ...

  3. Linux DNS 分离解析

    设置DNS分离解析可以对不同的客户端提供不同的域名解析记录.来自不同地址的客户机请求同一域名时,为其提供不同的解析结果. 安装 bind 包 [root@localhost ~]# yum insta ...

  4. linux服务器管理常用命令

    1.ps命令 (Processes Status) ps这个命令是查看系统进程,ps 是显示瞬间行程的状态,并不动态连续. ==============ps 的参数说明================ ...

  5. vs调试的时候无法命中断点

    visual studio 调试的时候如果没有命中断点,可能是启动的时候就出错了. 在文件Global.asax中, protected void Application_Error(object s ...

  6. SQL模糊查询的四种匹配模式

    执行数据库查询时,有完整查询和模糊查询之分,一般模糊语句如下: SELECT 字段 FROM 表 WHERE 某字段 Like 条件 一.四种匹配模式 关于条件,SQL提供了四种匹配模式: 1.% 表 ...

  7. Tensorflow简单实践系列(一):安装和运行

    TensorFlow 是谷歌开发的机器学习框架. 安装 TensorFlow 直接使用 pip 安装即可,添加豆瓣镜像可以加快速度: pip install tensorflow -i https:/ ...

  8. 攻击链路识别——CAPEC(共享攻击模式的公共标准)、MAEC(恶意软件行为特征)和ATT&CK(APT攻击链路上的子场景非常细)

    结合知识图谱对网络威胁建模分析,并兼容MITRE组织的CAPEC(共享攻击模式的公共标准).MAEC和ATT&CK(APT攻击链路上的子场景非常细)等模型的接入,并从情报中提取关键信息对知识图 ...

  9. PHP——仿造微信OpenId

    前言 这就是拿来玩的,其次假的就是假的,成不了真的! 代码 首先我观察了两个公众号关注后的生成openid的规则,发现了以下规则 1. OpenID都是28位 2. 前六位是有规律的 然后接下来就按着 ...

  10. Djiango-建立模型抽象基类

    创建一个抽象模型基类 ‘ 然后 ’base_model.py from django.db import models from datetime import date class BaseMode ...