В программировании возведение числа в степень — одна из самых распространенных операций. В языке Python для этого есть несколько способов, каждый из которых имеет свои особенности. В данной статье мы рассмотрим методы возведения в степень в Python.
Степень показывает сколько раз число умножается само на себя.
Пример:
2³ = 2 * 2 * 2 = 8 — два в третьей степени.
Существует три метода, возведения цифр в степень:
Легкий
Средний
Сложный
Рассмотрим каждый поподробнее.
Легкий уровень возведения в степень
Для возведения в степень можно использовать оператор **.
um = 3 ** 4 # то же самое что и 3 * 3 * 3 * 3
print(um) # 81
Оператор ** — это простой и универсальный способ возведения в степень, который выбирают многие программисты.
Средний уровень возведения в степень
pow (сокр. power) — функция возведения в степень
pow()
Функция pow() используется для возведения числа степень. Она эквивалентна оператору возведения в степень**.
chislo, stepen = 10, 3
print(pow(chislo, stepen)) # 1000
math.pow()
math.pow() является функцией из модуля math, которая также используется для возведения числа в степень, но принимает аргументы типа float и возвращает результат типа float. В отличие от функции pow(), она не поддерживает возможность деления по модулю.
import math
chislo, stepen = 10, 3
print(math.pow(chislo, stepen)) # 1000.0
Разница pow() и math.pow()
Казалось, бы делают они одно и то же, однако есть тонкая разница:
1. pow() может принимать три аргумента: число, степень, остаток от деления
r1 = pow(5, 3) # 5*5*5 = 125
r2 = pow(5, 3, 2) # равносильно (5*5*5) % 2
# то есть остаток от 125 при делении на 2 -> он равен одному
print(r1, r2) # 125 1
2. math.pow() использует ограниченную точность
import math
number, stepen, ostatok = 13, 100, 2
# (13 в степени 100) остаток деления на 2
print(math.pow(number, stepen) % ostatok) # 0.0
print(pow(number, stepen, ostatok)) # 1
Одинаковые действия, но результаты не совпадают. И это может оказаться критичным.
3. math.pow() всегда возвращает float
import math
print(math.pow(2, 6)) # 64.0
print(pow(2, 6)) # 64
Однако если результат дробный, то оба способа вернут float.
import math
print(math.pow(2.1, 6.2)) # 99.48546343115241
print(pow(2.1, 6.2)) # 99.48546343115241
4. math.pow() ломается на больших числах
import math
print(pow(2, 9999)) # без ошибок посчитает
print(math.pow(2, 9999)) # [Фатальная ошибка] OverflowError: math range error
5. Возможная разница в скорости
Напишем код, который измерит скорость выполнения.
pow():
pow1 = """
pow(2, 100)
"""
elapsed_time1 = timeit(pow1, number=100_000)
# запускаем код pow1 100к раз чтобы уменьшить погрешность
print(elapsed_time1)
math.pow():
from timeit import timeit
pow2 = """
import math
math.pow(2, 100)
"""
elapsed_time2 = timeit(pow2, number=100_000) # запускаем код pow2 100к раз
print(elapsed_time2)
Выходит, что pow() быстрее. Однако помните, многое зависит от устройства и платформы, на которой проводится тестирование. Некоторые сообщают, что у них math.pow() намного быстрее ?, даже если прописать setup="import math".
На другом компьютере и платформе результаты отличаются:
С этим arr1 = np.arange(8) теперь можно даже в pow() работать:
print(pow(arr1, 2)) # [ 0 1 4 9 16 25 36 49]
⚠️ Важно! При работе с ОС Windows возможна ошибка.
Как мы знаем, 2³¹ = 2147483648, тем не менее, numpy.power(2, 31) может выдать -2147483648. Что уже странно, однако numpy.power(2, 32) вовсе выдаст 0.
Причина проста, хоть и неожиданна и не особо озвучивается: нужно принудительно указать, чтобы получаемое число под капотом переводилось в тип longint (целое число, которое больше чем 2³¹).
Поэтому исправляем это следующим образом:
numpy.power(2, 31, dtype=numpy.longlong) # получим 2147483648, а не -2147483648
numpy.power(2, 32, dtype=numpy.longlong) # получим 4294967296, а не 0
Сравнение скорости работы
Давайте сравним скорость работы разных методов возведения числа в степень и выберем оптимальный для наших задач.
На основе 100000 запусков(number=100_000) получаем следующие результаты:
Место
Метод
Скорость
1
2**30
0.0009847609999837914
2
math.pow(2,30)
0.007375017000015305
3
pow(2,30)
0.013787384000011116
4
numpy.power(2,30)
0.09736091600001373
На порядок быстрее оказался встроенный оператор **. Перевес по времени выполнения pow() и math.pow() может координально измениться от платформы, на которой выполняется код.
Вывод: оператор ** самый простой, быстрый и универсальный.
Немного математической магии
При помощи языка Python можно делать математические вычисления. Расмотрим несколько математических трюков.
Квадратный корень (√)
Корень квадратный — знакомая операция:
√9 = 3
√81 = 9
Но существует математический трюк, как посчитать корень не запоминая и не путая всякие там sqr/sqrt:
print(9 ** 0.5) # 3.0
print(81 ** 0.5) # 9.0
То есть степень 1/2 это корень квадратный:
√64 = 64 ** (1/2) = 8.0
Отрицательная степень
Попробуем возвести отрицательную степень:
print(7 ** -3) # 0.0029154518950437317
Выглядит как что-то страшное. На самом деле всё довольно логично, если представить это дробью:
Пример отрицательной степени:
Поэтому 10-1=0.1
Нулевая степень
Математическая база: любое число в степени 0 это 1
Пример нулевой степени в коде:
print(54532 ** 0) # 1
print(0 ** 0) # 1
Заключение
Возведение в степень — одна из наиболее часто используемых операций в программировании. В статье были рассмотрены три метода возведения в степень в Python: оператор **, функции pow(), math.pow() и numpy.power().
Самым быстрым и универсальным способом является оператор **. Важно помнить, многое зависит от устройства и платформы, на которой пишется код. Также необходимо учитывать эффективность метода, читаемость и поддерживаемость в будущем.