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 次浏览

开启你的职业生涯

通过完成课程获得认证

开始学习
广告