Buscar..


Sintaxis

  • valor1 ** valor2
  • pow (valor1, valor2 [, valor3])
  • value1 .__ pow __ (value2 [, value3])
  • valor2 .__ rpow __ (valor1)
  • operator.pow (valor1, valor2)
  • operador .__ pow __ (valor1, valor2)
  • math.pow (value1, value2)
  • math.sqrt (valor1)
  • math.exp (value1)
  • cmath.exp (valor1)
  • math.expm1 (value1)

Raíz cuadrada: math.sqrt () y cmath.sqrt

El módulo math contiene la función math.sqrt() que puede calcular la raíz cuadrada de cualquier número (que se puede convertir en un float ) y el resultado siempre será un float :

import math

math.sqrt(9)                # 3.0
math.sqrt(11.11)            # 3.3331666624997918
math.sqrt(Decimal('6.25'))  # 2.5

La función math.sqrt() genera un ValueError si el resultado sería complex :

math.sqrt(-10)              

ValueError: error de dominio matemático

math.sqrt(x) es más rápido que math.pow(x, 0.5) o x ** 0.5 pero la precisión de los resultados es la misma. El módulo cmath es extremadamente similar al módulo math , excepto por el hecho de que puede calcular números complejos y todos sus resultados tienen la forma de a + bi. También puede usar .sqrt() :

import cmath

cmath.sqrt(4)  # 2+0j
cmath.sqrt(-4) # 2j

¿Qué pasa con la j ? j es el equivalente a la raíz cuadrada de -1. Todos los números se pueden poner en la forma a + bi, o en este caso, a + bj. a es la parte real del número como el 2 en 2+0j . Como no tiene una parte imaginaria, b es 0. b representa parte de la parte imaginaria del número como el 2 en 2j . Como no hay una parte real en esto, 2j también puede escribirse como 0 + 2j .

Exposiciónción utilizando builtins: ** y pow ()

Exponenciación se puede utilizar mediante el uso de la orden interna pow -Función o el ** operador:

2 ** 3    # 8
pow(2, 3) # 8

Para la mayoría de las operaciones aritméticas (todas en Python 2.x), el tipo de resultado será el del operando más amplio. Esto no es cierto para ** ; Los siguientes casos son excepciones a esta regla:

  • Base: int , exponente: int < 0 :

    2 ** -3
    # Out: 0.125 (result is a float)
    
  • Esto también es válido para Python 3.x.

  • Antes de Python 2.2.0, esto ValueError un ValueError .

  • Base: int < 0 o float < 0 , exponente: float != int

    (-2) ** (0.5)  # also (-2.) ** (0.5)    
    # Out: (8.659560562354934e-17+1.4142135623730951j) (result is complex)
    
  • Antes de Python 3.0.0, esto ValueError un ValueError .

El módulo operator contiene dos funciones que son equivalentes al operador ** :

import operator
operator.pow(4, 2)      # 16
operator.__pow__(4, 3)  # 64

o uno podría llamar directamente al método __pow__ :

val1, val2 = 4, 2
val1.__pow__(val2)      # 16
val2.__rpow__(val1)     # 16
# in-place power operation isn't supported by immutable classes like int, float, complex:
# val1.__ipow__(val2)   

Exposiciónción utilizando el módulo matemático: math.pow ()

El módulo math contiene otra función math.pow() . La diferencia con el operador incorporado pow() -function o ** es que el resultado es siempre un float :

import math
math.pow(2, 2)    # 4.0
math.pow(-2., 2)  # 4.0

Lo que excluye los cálculos con entradas complejas:

math.pow(2, 2+0j) 

TypeError: no se puede convertir complejo a flotar

y cálculos que conducirían a resultados complejos:

math.pow(-2, 0.5)

ValueError: error de dominio matemático

Función exponencial: math.exp () y cmath.exp ()

Tanto el módulo math como el módulo cmath contienen el número de Euler: e, y usarlo con la función pow() incorporada o el operador ** funciona principalmente como math.exp() :

import math

math.e ** 2  # 7.3890560989306495
math.exp(2)  # 7.38905609893065

import cmath
cmath.e ** 2 # 7.3890560989306495
cmath.exp(2) # (7.38905609893065+0j)

Sin embargo, el resultado es diferente y usar la función exponencial directamente es más confiable que la exponenciación math.e con base math.e :

print(math.e ** 10)       # 22026.465794806703
print(math.exp(10))       # 22026.465794806718
print(cmath.exp(10).real) # 22026.465794806718
#     difference starts here ---------------^

Función exponencial menos 1: math.expm1 ()

El módulo math contiene la función expm1() que puede calcular la expresión math.e ** x - 1 para x muy pequeña con mayor precisión que math.exp(x) o cmath.exp(x) permitiría:

import math

print(math.e ** 1e-3 - 1)  # 0.0010005001667083846
print(math.exp(1e-3) - 1)  # 0.0010005001667083846
print(math.expm1(1e-3))    # 0.0010005001667083417
#                            ------------------^

Para x muy pequeño la diferencia se hace más grande:

print(math.e ** 1e-15 - 1) # 1.1102230246251565e-15
print(math.exp(1e-15) - 1) # 1.1102230246251565e-15
print(math.expm1(1e-15))   # 1.0000000000000007e-15
#                              ^-------------------

La mejora es significativa en la computación científica. Por ejemplo, la ley de Planck contiene una función exponencial menos 1:

def planks_law(lambda_, T):
    from scipy.constants import h, k, c  # If no scipy installed hardcode these!
    return 2 * h * c ** 2 / (lambda_ ** 5 * math.expm1(h * c / (lambda_ * k * T)))

def planks_law_naive(lambda_, T):
    from scipy.constants import h, k, c  # If no scipy installed hardcode these!
    return 2 * h * c ** 2 / (lambda_ ** 5 * (math.e ** (h * c / (lambda_ * k * T)) - 1))

planks_law(100, 5000)        # 4.139080074896474e-19
planks_law_naive(100, 5000)  # 4.139080073488451e-19
#                                        ^---------- 

planks_law(1000, 5000)       # 4.139080128493406e-23
planks_law_naive(1000, 5000) # 4.139080233183142e-23
#                                      ^------------

Métodos mágicos y exponenciales: incorporados, matemáticos y matemáticos.

Suponiendo que tienes una clase que almacena valores puramente enteros:

class Integer(object):
    def __init__(self, value):
        self.value = int(value) # Cast to an integer
        
    def __repr__(self):
        return '{cls}({val})'.format(cls=self.__class__.__name__,
                                     val=self.value)
    
    def __pow__(self, other, modulo=None):
        if modulo is None:
            print('Using __pow__')
            return self.__class__(self.value ** other)
        else:
            print('Using __pow__ with modulo')
            return self.__class__(pow(self.value, other, modulo))
    
    def __float__(self):
        print('Using __float__')
        return float(self.value)
    
    def __complex__(self):
        print('Using __complex__')
        return complex(self.value, 0)

Usando la función pow incorporada o el operador ** siempre llama a __pow__ :

Integer(2) ** 2                 # Integer(4)
# Prints: Using __pow__
Integer(2) ** 2.5               # Integer(5)
# Prints: Using __pow__
pow(Integer(2), 0.5)            # Integer(1)
# Prints: Using __pow__  
operator.pow(Integer(2), 3)     # Integer(8)
# Prints: Using __pow__
operator.__pow__(Integer(3), 3) # Integer(27)
# Prints: Using __pow__

El segundo argumento del método __pow__() solo se puede suministrar usando la función builtinpow pow() o llamando directamente al método:

pow(Integer(2), 3, 4)           # Integer(0)
# Prints: Using __pow__ with modulo
Integer(2).__pow__(3, 4)        # Integer(0) 
# Prints: Using __pow__ with modulo  

Mientras que las funciones math siempre lo convierten en un float y usan el cálculo de flotación:

import math

math.pow(Integer(2), 0.5) # 1.4142135623730951
# Prints: Using __float__

cmath funciones intentan convertirlo en complex pero también pueden retroceder a float si no hay una conversión explícita a complex :

import cmath

cmath.exp(Integer(2))     # (7.38905609893065+0j)
# Prints: Using __complex__

del Integer.__complex__   # Deleting __complex__ method - instances cannot be cast to complex

cmath.exp(Integer(2))     # (7.38905609893065+0j)
# Prints: Using __float__

Ni math ni cmath funcionarán si también __float__() el __float__() :

del Integer.__float__  # Deleting __complex__ method

math.sqrt(Integer(2))  # also cmath.exp(Integer(2))

TypeError: se requiere un flotador

Exponenciación modular: pow () con 3 argumentos.

Al suministrar pow() con 3 argumentos pow(a, b, c) evalúa la exponenciación modular a b mod c :

pow(3, 4, 17)   # 13

# equivalent unoptimized expression:
3 ** 4 % 17     # 13

# steps:
3 ** 4          # 81
81 % 17         # 13

Para los tipos incorporados, el uso de exponenciación modular solo es posible si:

  • El primer argumento es un int
  • El segundo argumento es un int >= 0
  • El tercer argumento es un int != 0

Estas restricciones también están presentes en Python 3.x

Por ejemplo, uno puede usar la forma de 3 argumentos de pow para definir una función inversa modular :

def modular_inverse(x, p):
    """Find a such as  a·x ≡ 1 (mod p), assuming p is prime."""
    return pow(x, p-2, p)

[modular_inverse(x, 13) for x in range(1,13)]
# Out: [1, 7, 9, 10, 8, 11, 2, 5, 3, 4, 6, 12]

Raíces: raíz nth con exponentes fraccionarios

Si bien la función math.sqrt se proporciona para el caso específico de raíces cuadradas, a menudo es conveniente usar el operador de exponenciación ( ** ) con exponentes fraccionarios para realizar operaciones de raíz nth, como las raíces cúbicas.

La inversa de una exponenciación es la exponenciación por el recíproco del exponente. Entonces, si puedes calcular un número colocándolo en el exponente de 3, puedes encontrar la raíz cúbica de un número poniéndolo en el exponente de 1/3.

>>> x = 3
>>> y = x ** 3
>>> y
27
>>> z = y ** (1.0 / 3)
>>> z
3.0
>>> z == x
True

Cálculo de grandes raíces enteras

A pesar de que Python admite de forma nativa grandes enteros, tomar la raíz n de números muy grandes puede fallar en Python.

x = 2 ** 100
cube = x ** 3
root = cube ** (1.0 / 3)

OverflowError: largo int demasiado grande para convertirlo en flotante

Cuando trate con enteros tan grandes, necesitará usar una función personalizada para calcular la enésima raíz de un número.

def nth_root(x, n):
    # Start with some reasonable bounds around the nth root.
    upper_bound = 1
    while upper_bound ** n <= x:
        upper_bound *= 2
    lower_bound = upper_bound // 2
    # Keep searching for a better result as long as the bounds make sense.
    while lower_bound < upper_bound:
        mid = (lower_bound + upper_bound) // 2
        mid_nth = mid ** n
        if lower_bound < mid and mid_nth < x:
            lower_bound = mid
        elif upper_bound > mid and mid_nth > x:
            upper_bound = mid
        else:
            # Found perfect nth root.
            return mid
    return mid + 1

x = 2 ** 100
cube = x ** 3
root = nth_root(cube, 3)
x == root
# True


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow