我正在尝试使用辛普森积分规则对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)
答案 0 :(得分:1)
一切都错了。 x
是一个数组,每次调用f(x)
时,您都在整个数组上评估函数。由于n
是偶数而n-1
是奇数,因此最后一个循环中的y
是4*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
。