python上的simpson集成

时间:2019-01-14 05:52:35

标签: python-3.x numerical-methods

我正在尝试使用辛普森积分规则对f(x)= 2x从0到1进行数值积分,但会出现较大的误差。所需的输出为1,但是python的输出为1.334。有人可以帮我找到解决这个问题的方法吗? 谢谢。

import numpy as np

def f(x):
    return 2*x

def simpson(f,a,b,n):
    x = np.linspace(a,b,n)
    dx = (b-a)/n
    for i in np.arange(1,n):
        if i % 2 != 0:
            y = 4*f(x)
        elif i % 2 == 0:
            y = 2*f(x)
    return (f(a)+sum(y)+f(x)[-1])*dx/3

a = 0
b = 1
n = 1000
ans = simpson(f,a,b,n)
print(ans)

1 个答案:

答案 0 :(得分:1)

一切都错了。 x是一个数组,每次调用f(x)时,您都在整个数组上评估函数。由于n是偶数而n-1是奇数,因此最后一个循环中的y4*f(x),并根据其总和来计算出

然后n是段数。点数为n+1。正确的实现是

def simpson(f,a,b,n):
    x = np.linspace(a,b,n+1)
    y = f(x)
    dx = x[1]-x[0]
    return (y[0]+4*sum(y[1::2])+2*sum(y[2:-1:2])+y[-1])*dx/3

simpson(lambda x:2*x, 0, 1, 1000)

然后正确返回1.000。如果n是偶数,则可能要添加一个测试,如果不是,则将其增加一个。


如果您真的想保留循环,则需要在循环内实际求和。

def simpson(f,a,b,n):
    dx = (b-a)/n;
    res = 0; 
    for i in range(1,n): res += f(a+i*dx)*(2 if i%2==0 else 4); 
    return (f(a)+f(b) + res)*dx/3;

simpson(lambda x:2*x, 0, 1, 1000)

但是循环通常比矢量化操作慢,因此,如果您使用numpy,请使用矢量化操作。或者直接使用scipy.integrate.simps