Рассмотрим простой пример: ‘Найти сумму чисел в некотором диапазоне от нуля’. Сделать это можно различными способами. Представим наиболее очевидные способы решения на Python (v.3.8.x) и полученное для них время (через timeit
).
Первым способом решения может быть использование built-in функций sum
и range
:
from timeit import timeit
def get_sum_of_range(n=100_000_000):
return sum(range(n))
print(timeit.timeit(get_sum_of_range, number=1))
# -> 0.5181200389997684
Получаем время в 0.518 мс
.
Другой способ – использование numpy
:
from numpy import sum as np_sum, arange as np_arange
def get_sum_of_range_with_numpy(n=100_000_000):
return np_sum(np_arange(n))
print(timeit(get_sum_of_range_with_numpy, number=1))
# -> 0.15053598200029228
Теперь мы получили некоторый рост производительности – время 0.15 мс
.
Однако, наиболее быстрый способ представляет использованием простой формулы (n*(n-1))/2
из математики (в формуле используем целочисленное деление при помощи //
):
def get_sum_of_range_with_math(n=100_000_000):
return n * (n - 1) // 2
print(timeit(get_sum_of_range_with_math, number=1))
# -> 1.977000465558376e-06
И теперь результат в 1.977*10-6
или 0.000001977 мс
. Получаем значительный рост производительности при использовании мат. формулы. Естественно, что каждый из способов может нести свои недостатки в плане точности в рамках той или иной задачи.
Весь код для сравнения способов:
from timeit import timeit
from numpy import sum as np_sum, arange as np_arange
def get_sum_of_range(n=100_000_000):
return sum(range(n))
def get_sum_of_range_with_numpy(n=100_000_000):
return np_sum(np_arange(n))
def get_sum_of_range_with_math(n=100_000_000):
return n * (n - 1) // 2
print(timeit(get_sum_of_range, number=1))
print(timeit(get_sum_of_range_with_numpy, number=1))
print(timeit(get_sum_of_range_with_math, number=1))
# проверим, что все результаты совпадают
assert get_sum_of_range() == get_sum_of_range_with_numpy() == get_sum_of_range_with_math()
assert get_sum_of_range(42) == get_sum_of_range_with_numpy(42) == get_sum_of_range_with_math(42)
assert get_sum_of_range(357_357) == get_sum_of_range_with_numpy(357_357) == get_sum_of_range_with_math(357_357)
Подобная простая задачка показывает, как математика может упростить вам жизнь и повысить производительность вашего кода. В последнем случае даже поясняющий комментарий над формулой не требуется, ведь из названия функции уже понятно, что мы пытаемся сделать.
requests.request("GET", ...)
. Здесь мы не рассматриваем разработку аналитического ПО, так как в подобных случаях математика используется сплошь и рядом (вычисление среднего, медианы, среднего взвешенного и т.п.), а вопрос “зачем она нужна” отпадает изначально.