【数值分析】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 ... 
随机推荐
- CI隐藏入口文件index.php
			1.需要apache打开rewrite_module,然后修改httpd.conf的AllowOverride none 为AllowOverride All(里面,不同的环境目录不同) 2.在CI的 ... 
- 证券secuerity经济术语
			证券按其性质不同,证券可以分为证据证券.凭证证券和有价证券三大类.证据证券只是单纯地证明一种事实的书面证明文件,如信用证.证据.提单等:凭证证券是指认定持证人是某种私权的合法权利者和持证人纪行的义务有 ... 
- 机智云连接esp8266--远程控制风扇转速
			概述 下面我们使用esp8266开发板和机智云云端,实现如何将一个USB风扇,改造成可以远程控制转速的智能风扇. 1.准备工作 硬件: (1)esp8266开发板 (2)USB线 (3)USB风扇 软 ... 
- 【RAC】 RAC For W2K8R2 安装--创建ASM磁盘组(六)
			[RAC] RAC For W2K8R2 安装--创建ASM磁盘组(六) 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以 ... 
- dedeCMS 两个站共用同一个数据库 图片路径统一
			1 . 在 /include/extend.fun.php 中增加方法: function replaceurl($newurl){ $newurl=str_replace('src="/ ... 
- H3C 802.11 WEP加密原理
- 如何将scratch3.0的作业自动提交到后台数据库
			大家都知道Scratch3.0开发后,默认是可以下载文件到电脑,但是如果是作为商业系统来说,我们需要将作业自动的提交到后台,因此有了这篇文章. 首先,我们来分解下开发步骤: 1.在菜单栏新增一个上传到 ... 
- PAT甲级1011水题飘过
			题目分析:对于输入的数据分三条,选出每条中最大值记录下来,按照题目要求算出最大可能的获利即可 #include<iostream> using namespace std; ]; //k数 ... 
- selenium常用的API(六)浏览器窗口切换
			当使用selenium webdriver进行自动化测试打开多个窗口的时候,可能需要在不同的窗口间进行切换,webdriver提供的获取浏览器窗口句柄.切换句柄的方法如下: 获取当前窗口句柄 driv ... 
- 《exception》第九次团队作业:Beta冲刺与验收准备(第一天)
			一.项目基本介绍 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 Exception 作业学习目标 1.掌握软件黑盒测试技术:2.学会编制软件项目 ... 
