Там все не так. 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
.