Правило Симпсона заставляет работать вечно в Python
Я написал следующую функцию для оценки определенного интеграла функции с правилом Симпсона:
def fnInt(func, a, b):
if callable(func) and type(a) in [float] and type(b) in [float]:
if a > b:
return -1 * fnInt(func, b, a)
else:
y1 = nDeriv(func)
y2 = nDeriv(y1)
y3 = nDeriv(y2)
y4 = nDeriv(y3)
f = lambda t: abs(y4(t))
k = f(max(f, a, b))
n = ((1 / 0.00001) * k * (b - a) ** 5 / 180) ** 0.25
if n > 0:
n = math.ceil(n) if math.ceil(n) % 2 == 0 else math.ceil(n) + 1
else:
n = 2
x = (b - a) / n
ans = 0
for i in range(int((n - 4) / 2 + 1)):
ans += (x / 3) * (4 * func(a + x * (2 * i + 1)) + 2 * func(a + x * (2 * i + 2)))
ans += (x / 3) * (func(a) + 4 * func(a + x * (n - 1)) + func(b))
return ans
else:
raise TypeError('Data Type Error')
Кажется, однако, что всякий раз, когда я пытаюсь использовать эту функцию, на вывод уходит вечность. Есть ли способ, которым я могу переписать этот код, чтобы занять меньше времени?
1 ответ
Как один из упомянутых комментариев, профилирование кода покажет вам замедления. возможно nDeriv
медленный. Если у вас нет инструмента профилирования, вы можете поставить time()
Обзвонит каждый раздел кода и распечатает результаты. Более подробная информация здесь: Измерить время, прошедшее в Python?
Так что, если замедление заканчивается в вашем for
цикл, вот несколько вещей, которые вы можете попробовать:
Python может вычислять условие цикла на каждой итерации:
for i in range(int((n - 4) / 2 + 1)):
подсчитывать int((n - 4) / 2 + 1)
один раз до цикла.
- Не пересчитывайте вещи внутри циклов, которые не меняются. Например,
x / 3
будет пересчитываться при каждой итерации цикла, но она никогда не изменится. Сделайте это до начала цикла.
Точно так же ты делаешь 2 * i
дважды за каждую итерацию цикла.
Сложение происходит быстрее, чем умножение. Аргументы функции могут быть переписаны как:
xi = x * i a1 = a + xi + xi + x a2 = a1 + x
а затем сделать еще один шаг, вы также можете сделать заново xi
в качестве аккумулятора. То есть начнем с x = 0
тогда каждая итерация просто x += x
- Это, вероятно, очевидно, но если
func()
трудно рассчитать, эта функция будет экспоненциально медленной.
Возможно, Python делает для вас много простых оптимизаций, поэтому они могут не помочь, а просто хотели поделиться некоторыми идеями.