Правило Симпсона с помощью python

#python #python-3.x

#python #python-3.x

Вопрос:

Для моего численного курса я должен использовать правило Симпсона для аппроксимации интеграла от трех различных функций, которые перечислены ниже…. Мой код выполняется, но он не дает мне правильного приближения, и я не знаю почему….

 import math
def F(x):
    c = x * math.log(x)
    return c
def G(x):
    g = 2 / (x**2   4)
    return g
def H(x):
    h = x**2 * math.cos(x)
    return h
def simpsonRule(f, a, b, n):
    h = (b-a)/n
    k = 0
    z = 0
    for i in range(1, (n//2) - 1):
        k  = 2*f(a (2*i*h))

    for i in range(1, (n//2)):
        z  = 4*f(a ((2*i)-1)*h)    
    return (h*(f(a)   k   z   f(b))) / 3


AA = simpsonRule(F, 1, 2, 4)
CC = simpsonRule(G, 0, 2, 6)
DD = simpsonRule(H, 0, math.pi, 6)

print(AA)
print(CC)
print(DD)
  

Комментарии:

1. используется print() для отображения значений в переменных в разных местах и сравнения их с вычислениями на бумаге.

2. Я вижу три возможные проблемы: (1) код неверен — он неправильно использует алгоритм. (2) math.cos() ожидает радиус, но вы используете градусы (3) float в компьютере не может сохранять все возможные значения, поэтому он сохраняет аппроксимацию, и тогда результат не может быть идеальным. т. е. 0.1 0.2 == 0.3 дает False

3. Можете ли вы поделиться ожидаемым результатом и для входных данных

Ответ №1:

Я считаю, что проблема в том, что верхний предел ваших range() вызовов отключен на 1. Верхний предел никогда не достигается, поэтому он должен быть выше того, что вы хотите. Я включил дополнительный тестовый пример, sin(x) , для которого я знал правильный ответ (~ 1):

 import math

def E(x):
    return math.sin(x)

def F(x):
    return x * math.log(x)

def G(x):
    return 2 / (x**2   4)

def H(x):
    return x**2 * math.cos(x)

def simpsonRule(f, a, b, n):
    h = (b - a) / n
    k = 0
    z = 0

    for i in range(1, n // 2):
        k  = 2 * f(a   2 * i * h)

    for i in range(1, n // 2   1):
        z  = 4 * f(a   (2 * i - 1) * h)

    return h * (f(a)   k   z   f(b)) / 3.0

AA = simpsonRule(F, 1, 2, 4)
CC = simpsonRule(G, 0, 2, 6)
DD = simpsonRule(H, 0, math.pi, 6)
EE = simpsonRule(E, 0, math.pi / 2, 100)

print(AA)
print(CC)
print(DD)
print(EE)
  

ВЫВОД

 > python3 test.py
0.6363098297969493
0.7853979452340107
-6.274868388453119
1.0000000003382359
> 
  

Комментарии:

1. Результат соответствует тому, что я сделал вручную. Спасибо, но я все еще не понимаю, почему вы изменили циклы for так, как вы это сделали … если вы посмотрите на алгоритм, то ограничение от 1 до 1 / n — 1 имеет функцию, умноженную на 2, но вы умножили ее на 4 и также изменили другую… Я просто не понимаю, почему

2. @JozyMan, я не знаю, о чем ты спрашиваешь. Мой код идентичен вашему опубликованному коду, за исключением того, что верхний предел range() вызовов на 1 больше, и я удалил ненужные скобки. Я не вижу никаких изменений 2 против 4 или отмены.

Ответ №2:

В случае, если вы используете Python 2.x, проблема может быть вызвана типами переменных. Все переменные в правой части эксперимента h = (b-a)/n являются int , поэтому интерпретатор предполагает, что h int это также должно быть. Проблема может быть решена путем преобразования типа

 a = float(a)
b = float(b) 
  

вставлено перед этим выражением.

Упомянутое выше поведение характерно для Python 2, и оно было исправлено в Python 3, предполагая float , что в этой ситуации. Смотрите здесь больше примеров с приведением типов в Python.

Вывод без преобразования:

 0.0
0
-1.36541969235
  

Вывод с преобразованием:

 0.208501009808
0.577327327327
-1.36541969235
  

Комментарии:

1. h было бы только int на Python 2. Спрашивающий говорит, что они на Python 3. Хотя они могут ошибаться в этом, публикация ответа, специфичного для Python 2, без предварительного изучения версии, кажется преждевременной.

2. Спасибо за предложение. Я отредактировал ответ, указав, что он применим для Python 2

3. В вопросе есть два тега: один — общий вопрос python, а другой — специфичный для Python 3. Итак, я решил, что вопрос не ограничивается только Python 3.

4. Во-первых, python тег был отредактирован другим пользователем. Во-вторых, вопросы, относящиеся к Python 3, должны быть помечены как python и python-3.x . Предполагается, что вопросы, зависящие от версии, не должны иметь python-3.x тега. В-третьих, зачем python-3.x вообще нужен тег, если спрашивающий запускал (или считал, что он запускает) Python 2?

5. Это своего рода априорное знание или где-то написано об обоих тегах? Как я должен знать, что добавлено другим пользователем? Кто-то может добавить оба тега, если он не уверен.