Python模擬Lagrange插值代碼及結果
題目:exp(x)(函數可變)在[0,4]的n階多項式插值及誤差
思路
主要思路分爲兩部分:
- 如何計算n階多項式插值?
- 誤差如何計算?
首先第一個部分:
對於lagrange插值函數的計算,首先我們觀察公式:
其中,
公式寫在代碼中就是連乘,並且需要循環嵌套。並且當分母爲零(相減兩項相同時),乘式應爲1。
第二個部分更加簡單,這裏的誤差我們取絕對誤差,即爲解析值-真值。需要考慮的是誤差的變化。需要觀察兩種情況:固定插值次數,變換x看誤差變化;固定x,增加插值次數看誤差變化。
代碼部分
#exp(x)在[0,4]的n階多項式插值及誤差
import math
import numpy as np
import matplotlib.pyplot as plt
def truev(x):
a=np.sin(x)
return a
#計算n+1個真值
def truex(x0,xn,n):
v = np.zeros((n+1,2))#開闢一個數組存x以及對應的y值
h = (xn-x0)/n#步長
for i in range(n+1):
v[i][0]= x0+(h * i)
v[i][1]=truev(v[i][0])
return v;
def truearrayx(x0,xn):
h=0.001;
o=int((xn-x0)/h)
m = np.zeros((o,2))
s = np.zeros(o)
z = np.zeros(o)
#print(m);#開闢一個數組存x以及對應的y值
for i in range(o):
s[i]= x0+(h * i)
#print(x[i])
z[i]=truev(s[i])
return s,z
def Lagrangev(x0,xn,arr,n,t):#輸入值:存放真值的數組、插值次數;輸出值:函數結果
p=0
l=np.zeros(n+1)
d=np.zeros(n+1)
if (((t-x0)*n)%(xn-x0)==0 ):#取端點值得真值
t=int(((t-x0)*n)/(xn-x0))
print(t)
p=arr[t][1]
else:
for j in range(n+1):
l[j]=arr[j][1]
for k in range(n+1):
if(arr[j][0]-arr[k][0]==0):
d[k]=1
l[j]=l[j]
else:
d[k]=arr[j][0]-arr[k][0]
l[j]=l[j]*(t-arr[k][0])/(d[k])
for j in range(n+1):
p=p+l[j]#求和
return p
def lagrangarrayx(x0,xn,arr,n):
g = np.zeros(n+1)
f = np.zeros(n+1)
h=(xn-x0)/n
for i in range(n+1):
g[i]= x0+(h * i)
f[i]=Lagrangev(x0,xn,arr,n,g[i])
return g,f
def errorx(x0,xn,n,x):#輸入起始值;終值;插值次數;x值
b=truex(x0,xn,n)
a=Lagrangev(x0,xn,b,n,x)
c=truev(x)
errorv=a-c
return errorv
#畫圖:誤差曲線;問題,x應該取何值?將x軸離散化求值,而且要把error爲0的點避開
def errorarrayx(x0,xn,n):
h=(xn-x0)/n
m = np.zeros((n,2))
u = np.zeros(n)
r = np.zeros(n)
for i in range(n):
m[i][0]= x0+(h * i)
u[i]=m[i][0]
m[i][1]=errorx(x0,xn,n,m[i][0])
r[i]=m[i][1]
return u,r
x0=0;xn=4;n1=8;n=4;h=(xn-x0)/n
e=truex(x0,xn,n)
e1=truex(x0,xn,n1)
(a,b)=truearrayx(x0,xn)
(c,d)=lagrangarrayx(x0,xn,e,n)
(c1,d1)=lagrangarrayx(x0,xn,e1,n1)
fig = plt.figure(num=1, figsize=(30, 15),dpi=80)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False#設置漢語顯示
plt.plot(a,b, label='true values', linewidth=4, color='fuchsia')
plt.plot(c,d, label='n=4 Lagrange interpolation', linewidth=3, color='lawngreen', marker='o',
markerfacecolor='beige', markersize=6)
plt.plot(c1,d1, label='n=8 Lagrange interpolation', linewidth=3, color='cyan', marker='o',
markerfacecolor='coral', markersize=6)
for x, y in zip(c, d):
plt.text(x, y, y, ha='center', va='bottom', fontsize=10,rotation=5)
for x1, y1 in zip(c1, d1):
plt.text(x1, y1, y1, ha='center', va='bottom', fontsize=10,rotation=5)
plt.legend(loc="upper right",fontsize="xx-large")
plt.xlabel("x")
plt.ylabel("Values")
plt.title('Result Of Lagrange Interpolation ',fontsize='xx-large',fontweight='black')
plt.show()
代碼運行結果
插值n=4;n=8結果:
插值n=4;n=8結果:
插值n=4;n=8結果:
分析誤差
對於同一n(假設爲8)不同的x
代碼如下:
#誤差曲線
fig = plt.figure(num=1, figsize=(30, 15),dpi=150)
(a,b)=errorarrayx(0,4,8)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False#設置漢語顯示
plt.plot(a,b, label=' error of n=20 Lagrange interpolation', linewidth=3, color='red', marker='o',
markerfacecolor='blue', markersize=6)
for x, y in zip(a,b):
plt.text(x, y, y, ha='center', va='bottom', fontsize=6)
plt.xlabel("x")
plt.ylabel("Error")
plt.title('Error Of Lagrange Interpolation with different x ',fontsize='xx-large',fontweight='black')
plt.show()
結果
對於同一x(固定取3.44),取不同n
代碼如下:
#誤差曲線
fig = plt.figure(num=1, figsize=(30, 15),dpi=150)
#(a,b)=errorarrayx(0,4,8)
b=errorarrayn(0,4,3.44,19)#輸入n取值的最大值
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False#設置漢語顯示
# plt.plot(a,b, label=' error of n=20 Lagrange interpolation', linewidth=3, color='red', marker='o',
# markerfacecolor='blue', markersize=6)
# for x, y in zip(a,b):
# plt.text(x, y, y, ha='center', va='bottom', fontsize=6)
# plt.xlabel("x")
# plt.ylabel("Error")
# plt.title('Error Of Lagrange Interpolation with different x ',fontsize='xx-large',fontweight='black')
plt.plot(range(20),b, label=' error of n=20 Lagrange interpolation', linewidth=3, color='red', marker='o',
markerfacecolor='blue', markersize=6)
for x, y in zip(range(20),b):
plt.text(x, y, y, ha='center', va='bottom', fontsize=6,rotation=10)
plt.xlabel("n")
plt.ylabel("Error")
plt.title('Error Of Lagrange Interpolation with different n ',fontsize='xx-large',fontweight='black')
plt.show()
結果
Problem
當x靠近端點值(eg:取x=3.98),n增大到一定程度時,會出現所謂的龍格現象。如下圖所示:
龍格現象:
一般情況下,多項式的次數越多,需要的數據就越多,而預測也就越準確。插值次數越高,插值結果越偏離原函數的現象稱爲龍格現象。
插值結果及誤差分析
由上述圖中我們可以發現:
- 拉格朗日插值函數比較接近原函數;
- 固定n,誤差隨x值變化沒有什麼規律。有幾個插值節點,誤差就有幾個零點。在零點周圍,誤差有正有負;
- 固定x,誤差隨着n值的增大越來越小。插值次數增加到一定程度,會產生龍格現象。