usar define python math built-in pow

define - Exponenciales en python x.** y vs math.pow(x, y)



python cosine function (4)

Bueno, son para diferentes tareas, realmente.

Use pow (equivalente a x ** y con dos argumentos) cuando quiera una aritmética entera.

Y use math.pow si cualquiera de los argumentos es flotante, y quiere salida flotante.

Para una discusión sobre las diferencias entre pow y math.pow , vea esta question .

¿Cuál es más eficiente usando math.pow o the ** operator? ¿Cuándo debería usar uno sobre el otro?

Hasta ahora sé que x**y puede devolver un int o un float si usa un decimal la función pow devolverá un float

import math print math.pow(10, 2) print 10. ** 2


Solo para el protocolo: el operador ** llama a la función pow incorporada que acepta un tercer argumento opcional (módulo) si los primeros dos argumentos son tipos enteros.

Entonces, si tiene la intención de calcular los restos de las potencias, use la función incorporada. El math.pow puede darte resultados falsos:

import math base = 13 exp = 100 mod = 2 print math.pow(base, exp) % mod print pow(base, exp, mod)

Cuando ejecuté esto, obtuve 0.0 en el primer caso que obviamente no puede ser cierto, porque 13 es impar (y por lo tanto todos sus poderes integrales). La versión math.pow usa una precisión limitada que causa un error.

En aras de la equidad, debemos decir que math.pow puede ser mucho más rápido:

import timeit print timeit.timeit("math.pow(2, 100)",setup=''import math'') print timeit.timeit("pow(2, 100)")

Esto es lo que obtengo como salida:

0.240936803195 1.4775809183

Algunos ejemplos en línea


Usar el operador de energía ** será más rápido ya que no tendrá la sobrecarga de una llamada a función. Puedes ver esto si desarmas el código de 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

Tenga en cuenta que estoy usando una variable i como exponente aquí porque las expresiones constantes como 7. ** 5 realidad se evalúan en tiempo de compilación.

Ahora, en la práctica, esta diferencia no importa demasiado, como se puede ver cuando se mide el tiempo:

>>> 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

Entonces, mientras pow y math.pow son casi el doble de lentos, todavía son lo suficientemente rápidos para que no les importe demasiado. A menos que pueda identificar la exponenciación como un cuello de botella, no habrá una razón para elegir un método sobre el otro si la claridad disminuye. Esto se aplica especialmente ya que pow ofrece una operación de módulo integrada, por ejemplo.

Alfe hizo una buena pregunta en los comentarios de arriba:

timeit muestra que math.pow es más lento que ** en todos los casos. ¿ math.pow() qué sirve math.pow() ? ¿Alguien tiene una idea de dónde puede ser de alguna ventaja?

La gran diferencia de math.pow tanto para el pow incorporado como para el power operator ** es que siempre usa la semántica de float. Por lo tanto, si usted, por alguna razón, quiere asegurarse de obtener una flotación como resultado, entonces math.pow asegurará esta propiedad.

Pensemos en un ejemplo: tenemos dos números, i y j , y no tenemos idea de si son flotantes o enteros. Pero queremos tener un resultado flotante de i^j . Entonces, ¿qué opciones tenemos?

  • Podemos convertir al menos uno de los argumentos en un flotante y luego hacemos i ** j .
  • Podemos hacer i ** j y convertir el resultado en un flotante (la exponenciación flotante se usa automáticamente cuando i o j son flotantes, por lo que el resultado es el mismo).
  • Podemos usar math.pow .

Entonces, probemos esto:

>>> 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

Como puede ver, ¡ math.pow es realmente más rápido! Y si lo piensas bien, la sobrecarga de la llamada a función también se ha ido ahora, porque en todas las otras alternativas tenemos que llamar a float() .

Además, podría valer la pena señalar que el comportamiento de ** y pow puede __pow__ implementando el __pow__ especial __pow__ (y __rpow__ ) para tipos personalizados. Entonces, si no quieres eso (por alguna razón), usar math.pow no hará eso.


** es de hecho más rápido que math.pow() , pero si desea una función cuadrática simple como en su ejemplo, es aún más rápido usar un producto.

10.*10.

será más rápido entonces

10.**2

La diferencia no es grande y no es notorio con una operación (usando timeit ), pero con una gran cantidad de operaciones puede ser significativa.