Python數值積分中的辛普森法則建模


辛普森法則是一種非常強大的數值積分工具。為了在需要較少劃分的情況下最大限度地提高精度,辛普森法則使用加權因子來計算積分。梯形法則只考慮兩個點,𝑥𝑖和𝑥𝑖+1,來估計梯形的面積,但辛普森法則在每一輪中使用多於兩個點(或許多條帶)(參見下圖)。透過加權各種標準來更新不同點的𝑓(𝑥)值,以減少誤差。

辛普森1/3法則

這種方法同時計算兩條帶的面積,因此每次考慮三個不同的“x”值。為了覆蓋整個域,條帶數n必須是偶數。

對於前兩條帶,辛普森1/3法則公式如下:

$$\mathrm{A=\frac{1}{3}h(f(x_0)+4f(x_1)+f(x_2))}$$

因此,條帶配對的總數為:

$$\mathrm{I=\frac{1}{3}h((x_0)+4f(x_1)+f(x_2)))+\frac{1}{3}h(f(x_2)+4f(x_3)+f(x_4))+...}$$

$$\mathrm{+\frac{1}{3}h(f(x_{n-4})+4f(x_{n-3})+f(x_{n-2}))}$$

$$\mathrm{+\frac{1}{3} h(f(x_{n-2})+4f(x_{n-1})+f(x_n))}$$

為了簡化程式設計,簡化形式可以寫成:

$$\mathrm{I=\frac{1}{3}h{(f(x_0)+f(x_n))+4(f(x_1)+f(x_3)+...+f(x_{n-3})+f(x_{n-1}))+2(f(x_2)+f(x_4)+...+f(x_{n-4})+f(x_{n-2}))}}$$

最後,將各項寫成求和形式將得到:

$$\mathrm{I=\frac{1}{3}h{(f(a)+f(b))+\sum^{n-1}_{i=1,3,5}4f(x_i)+\sum^{n-2}_{i=2,4,6}2f(x_i)}}$$

這裡,重要的是要記住“n”是偶數。

假設我們想要執行以下積分:

$$\mathrm{\int^{\frac{\pi}{2}}_0x\:sin(x)dx}$$

現在可以編寫程式設計過程:

匯入模組

# Importing module for array
from numpy import * 

定義需要進行積分的函式

# Defining the function
def f(x):
   return x*sin(x)

輸入函式的左右極限(𝑎, 𝑏)以及要將面積劃分的梯形數𝑛 (**𝑛必須是偶數**)。

# Defining function domain (i.e. Left and Right limits)
a=0
b=pi/2
# Defining number of trapezoids
n=4

計算每個梯形的寬度(ℎ = (𝑏 − 𝑎)/𝑛)

# Evaluating the width of trapezoids
h=(b-a)/n

建立𝑥陣列。由於梯形數為n,所以𝑥的個數為𝑛 + 1,即“𝑥”陣列將有𝑛 + 1個元素。這是因為NumPy陣列的索引從0開始,而不是從1開始。

# Creating array of x
# (Note: For n trapezoids (no. of x's/nodes = n+1))
x=linspace(a,b,n+1)

首先計算$\mathrm{\frac{1}{2}(𝑓(𝑎) + 𝑓(𝑏))}$並將結果賦值給變數“I”。

# First term of I
I=0.5*(f(a)+f(b))

執行一個迴圈,用於計算𝑥 = 1到𝑥 = 𝑛的公式1(因為有𝑛 + 1個節點)。這裡需要注意的是,當主迴圈中的索引j為偶數時,將計算$\mathrm{2𝑓(𝑥_𝑖)}$,否則將計算$\mathrm{4𝑓(𝑥_𝑖)}$項。

# Summing over remaining n-2 trapezoids
for j in range(1,n):
   if j%2==0:
      I=I+2*f(x[j])
   else:
      I=I+4*f(x[j])

最後,在迴圈外部,將“I”乘以h/3並將結果賦值給“I”,然後列印結果。

I=(h/3)*I
print(f'I = {round(I,6)}')

完整的Python程式如下:

from numpy import *
def f(x):
   return x*sin(x)
# Left and Right limits
a=0
b=pi/2
# Number of trapezoids
n=4
# Width of trapezoid
h=(b-a)/n
# array of x
# For n trapezoids (no. of nodes=n+1)
x=linspace(a,b,n+1)
# First term of I
I=(f(a)+f(b))
# Summing over remaining n-2 trapezoids
for j in range(1,n):
   if j%2==0:
      I=I+2*f(x[j])
   else:
      I=I+4*f(x[j])
I=(h/3)*I
print(f'I = {round(I,6)}')

輸出

對於n=4,程式返回I = 0.999591,這非常接近精確結果。

辛普森3/8法則

它與辛普森1/3法則的區別僅在於考慮了三條帶,這意味著每次都包含四個點。前三條帶的公式如下:

$$\mathrm{A=\frac{3}{8}h(f(x_0)+3f(x_1)+3f(x_2)+f(x_3))}$$

因此,所有條帶配對的總和為。

$$\mathrm{I=\frac{3}{8}[(f(x_0)+3f(x_1)+3f(x_2)+f(x_3))+(f(x_3)+3f(x_4)+3f(x_5)+f(x_6))+(f(x_{n-3})+3f(x_{n-2}+3f(x_n-1)+f(x_n))]}$$

最後將各項寫成求和形式,以簡化程式設計。

$$\mathrm{I=\frac{3}{8}[(f(a)+f(b))+\sum^{n-2}_{i=1,4,7}3[f(x_i)+f(x_{i+1})]+\sum^{n-3}_{i=3,6,9}2f(x_i)]}$$

條帶的數量n必須是3的倍數。我們將使用兩個迴圈,一個用於第二項,一個用於第三項,因為從上面的公式可以明顯看出,第二項從1開始,第三項從3開始。迴圈計數器將以三遞增。

在這裡,我們將採用與之前的1/3情況相同的示例:

$$\mathrm{\int^\frac{\pi}{2}_0x\:sin(x)dx}$$

與1/3情況相比,演算法的唯一區別在於求解公式2的方式。如果你仔細觀察,你會理解到右邊第二項的索引從1開始,而第三項的索引從3開始。因此,迴圈必須分成兩部分,如下所示:

# Summing over remaining n-2 trapezoids
j=1
while j<n:
   I=I+3*(f(x[j])+f(x[j+1]))
   j=j+3
j=3
while j<n:
   I=I+2*f(x[j])
   j=j+3
I=(3*h/8)*I

完整的Python程式如下:

from numpy import *
def f(x):
   return x*sin(x)
# Left and Right limits
a=0
b=pi/2

# Number of trapezoids
n=6

# Width of trapezoid
h=(b-a)/n

# array of x
# For n trapezoids (no. of nodes=n+1)
x=linspace(a,b,n+1)

# First term of I
I=(f(a)+f(b))

# Summing over remaining n-2 trapezoids
j=1
while j<n:
   I=I+3*(f(x[j])+f(x[j+1]))
   j=j+3
j=3
while j<n:
   I=I+2*f(x[j])
   j=j+3
I=(3*h/8)*I
print(f'I = {round(I,6)}')

輸出

對於“n=6”,程式返回:

I = 0.999819

結論

在本教程中,我們學習瞭如何在Python中建模辛普森法則以進行數值積分。我們詳細闡述並編寫了1/3法則和3/8法則的演算法。

更新於:2023年10月4日

650 次瀏覽

開啟你的職業生涯

透過完成課程獲得認證

開始學習
廣告