Питон корень квадратный

Экспоненты в python x. ** y vs math.pow (x, y)

Использование оператора питания ** будет быстрее, поскольку у него не будет накладных расходов на вызов функции. Вы можете увидеть это, если разобрать код Python:

>>> dis.dis(‘7. ** i’) 1 0 LOAD_CONST 0 (7.0) 3 LOAD_NAME 0 (i) 6 BINARY_POWER 7 RETURN_VALUE >>> dis.dis(‘pow(7., i)’) 1 0 LOAD_NAME 0 (pow) 3 LOAD_CONST 0 (7.0) 6 LOAD_NAME 1 (i) 9 CALL_FUNCTION 2 (2 positional, 0 keyword pair) 12 RETURN_VALUE >>> dis.dis(‘math.pow(7, i)’) 1 0 LOAD_NAME 0 (math) 3 LOAD_ATTR 1 (pow) 6 LOAD_CONST 0 (7) 9 LOAD_NAME 2 (i) 12 CALL_FUNCTION 2 (2 positional, 0 keyword pair) 15 RETURN_VALUE

Обратите внимание, что я использую переменную i в качестве экспоненты здесь, потому что постоянные выражения, такие как 7. ** 5 , фактически вычисляются во время компиляции.

Теперь, на практике, это различие не так важно, как вы можете видеть, когда это время:

>>> from timeit import timeit >>> timeit(‘7. ** i’, setup=’i = 5′) 0.2894785532627111 >>> timeit(‘pow(7., i)’, setup=’i = 5′) 0.41218495570683444 >>> timeit(‘math.pow(7, i)’, setup=’import math; i = 5′) 0.5655053168791255

Итак, хотя pow и math.pow примерно в два раза медленнее, они все еще достаточно быстры, чтобы не волноваться. Если вы не сможете на самом деле идентифицировать возведение в степень как узкое место, не будет причины выбирать один метод над другим, если ясность уменьшается. Это особенно справедливо, так как pow предлагает интегрированную модульную операцию, например.

Альф спросил хороший вопрос в комментариях выше:

timeit показывает, что math.pow медленнее, чем ** во всех случаях. Что такое math.pow() хорошо в любом случае? Есть ли у кого-нибудь идея, где это может быть какое-то преимущество тогда?

Большая разница в math.pow как встроенной мощности, так и оператора мощности ** заключается в том, что она всегда использует семантику float. Поэтому, если вы по какой-то причине хотите убедиться, что вы math.pow float в результате, то math.pow обеспечит это свойство.

Давайте приведем пример: у нас есть два числа, i и j , и понятия не имею, являются ли они поплавками или целыми числами. Но мы хотим получить результат float i^j . Итак, какие у нас варианты?

  • Мы можем преобразовать хотя бы один из аргументов в float, а затем сделать i ** j .
  • Мы можем сделать i ** j и преобразовать результат в float (float exponentation автоматически используется, когда i или j являются float, поэтому результат тот же).
  • Мы можем использовать math.pow .

Итак, давайте проверим это:

>>> timeit(‘float(i) ** j’, setup=’i, j = 7, 5′) 0.7610865891750791 >>> timeit(‘i ** float(j)’, setup=’i, j = 7, 5′) 0.7930400942188385 >>> timeit(‘float(i ** j)’, setup=’i, j = 7, 5′) 0.8946636625872202 >>> timeit(‘math.pow(i, j)’, setup=’import math; i, j = 7, 5′) 0.5699394063529439

Как вы можете видеть, math.pow на самом деле быстрее! И если вы подумаете об этом, накладные расходы от вызова функции также исчезли, потому что во всех остальных альтернативах мы должны вызвать float() .

Кроме того, можно отметить, что поведение ** и pow может быть переопределено путем реализации специального __pow__ (и __rpow__ ) для настраиваемых типов. Поэтому, если вы этого не хотите (по какой-либо причине), использование math.pow этого не сделает.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *