Suche…


Syntax

  • value1 ** value2
  • pow (wert1, wert2 [, wert3])
  • value1 .__ pow __ (value2 [, value3])
  • value2 .__ rpow__ (value1)
  • operator.pow (Wert1, Wert2)
  • Operator .__ Pow __ (Wert1, Wert2)
  • math.pow (Wert1, Wert2)
  • math.sqrt (value1)
  • math.exp (Wert1)
  • cmath.exp (Wert1)
  • math.expm1 (Wert1)

Quadratwurzel: math.sqrt () und cmath.sqrt

Das math Modul enthält die math.sqrt() -Funktion, die die Quadratwurzel einer beliebigen Zahl berechnen kann (die in einen float ). Das Ergebnis ist immer ein float :

import math

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

Die math.sqrt() Funktion löst einen ValueError wenn das Ergebnis complex :

math.sqrt(-10)              

ValueError: mathematischer Domänenfehler

math.sqrt(x) ist schneller als math.pow(x, 0.5) oder x ** 0.5 aber die Genauigkeit der Ergebnisse ist gleich. Das cmath Modul ist dem math Modul sehr ähnlich, abgesehen davon, dass es komplexe Zahlen berechnen kann und alle Ergebnisse in Form von + bi vorliegen. Es kann auch .sqrt() :

import cmath

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

Was ist mit dem j ? j ist das Äquivalent zur Quadratwurzel von -1. Alle Zahlen können in der Form a + bi oder in diesem Fall a + bj eingegeben werden. a ist der Realteil der Zahl wie 2 in 2+0j . Da es keinen Imaginärteil hat, b 0 ist b Teil des Imaginärteils der Zahl wie die in 2 repräsentiert 2j . Da es hier keinen Realteil gibt, kann 2j auch als 0 + 2j .

Potenzierung mit Builtins: ** und pow ()

Die Potenzierung kann mit der eingebauten pow oder dem Operator ** werden:

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

Für die meisten (alle in Python 2.x) arithmetischen Operationen ist der Ergebnistyp der Typ des breiteren Operanden. Dies gilt nicht für ** ; Die folgenden Fälle sind Ausnahmen von dieser Regel:

  • Basis: int , Exponent: int < 0 :

    2 ** -3
    # Out: 0.125 (result is a float)
    
  • Dies gilt auch für Python 3.x.

  • Vor Python 2.2.0 wurde ein ValueError .

  • Basis: int < 0 oder float < 0 , Exponent: float != int

    (-2) ** (0.5)  # also (-2.) ** (0.5)    
    # Out: (8.659560562354934e-17+1.4142135623730951j) (result is complex)
    
  • Vor Python 3.0.0 wurde ein ValueError .

Der operator Modul enthält zwei Funktionen, die den äquivalent ** -Operator:

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

oder man könnte die __pow__ Methode direkt aufrufen:

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)   

Potenzierung mit dem math Modul: math.pow ()

Das math -Modul enthält eine weitere math.pow() Funktion. Der Unterschied zur eingebauten pow() -Funktion oder dem ** Operator besteht darin, dass das Ergebnis immer ein float

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

Was schließt Berechnungen mit komplexen Eingaben aus:

math.pow(2, 2+0j) 

TypeError: Komplexe können nicht in Float konvertiert werden

und Berechnungen, die zu komplexen Ergebnissen führen würden:

math.pow(-2, 0.5)

ValueError: mathematischer Domänenfehler

Exponentialfunktion: math.exp () und cmath.exp ()

Sowohl das math als auch das cmath Modul enthalten die Euler-Nummer: e und die Verwendung der eingebauten pow() oder des ** -Operators funktioniert meistens wie 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)

Das Ergebnis ist jedoch anders und die direkte Verwendung der Exponentialfunktion ist zuverlässiger als die eingebaute Exponentiation mit der Basis math.e :

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

Exponentialfunktion minus 1: math.expm1 ()

Das math Modul enthält die expm1() -Funktion, die den Ausdruck math.e ** x - 1 für sehr kleines x mit einer höheren Genauigkeit math.exp(x) als math.exp(x) oder cmath.exp(x) :

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

Bei sehr kleinen x wird der Unterschied größer:

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

Die Verbesserung ist im wissenschaftlichen Computing signifikant. Zum Beispiel enthält das Plancksche Gesetz eine Exponentialfunktion minus 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
#                                      ^------------

Magische Methoden und Exponentiation: Builtin, Mathe und Cmath

Angenommen, Sie haben eine Klasse, die rein ganzzahlige Werte speichert:

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)

Mit der eingebauten pow Funktion oder dem Operator ** wird immer __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__

Das zweite Argument der __pow__() -Methode kann nur über das BuiltinPow pow() oder durch direktes Aufrufen der Methode angegeben werden:

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

Während die math immer in ein float konvertieren und die Float-Berechnung verwenden:

import math

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

cmath -Funktionen versuchen , es zu konvertieren complex , kann aber auch zu Rückfall float , wenn es keine explizite Konvertierung ist 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__

Weder math noch cmath funktionieren, wenn auch die __float__() -Methode fehlt:

del Integer.__float__  # Deleting __complex__ method

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

TypeError: ein Float ist erforderlich

Modulare Exponentiation: pow () mit 3 Argumenten

Wenn Sie pow() mit 3 Argumenten pow(a, b, c) bewertet pow(a, b, c) die modulare Exponentiation a b mod c :

pow(3, 4, 17)   # 13

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

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

Bei eingebauten Typen ist die modulare Potenzierung nur möglich, wenn:

  • Das erste Argument ist ein int
  • Zweites Argument ist ein int >= 0
  • Das dritte Argument ist ein int != 0

Diese Einschränkungen sind auch in Python 3.x vorhanden

Zum Beispiel kann man mit der 3-Argument-Form von pow eine modulare inverse Funktion definieren:

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]

Wurzeln: n-te Wurzel mit gebrochenen Exponenten

Während die math.sqrt Funktion für den speziellen Fall der Quadratwurzeln vorgesehen ist, ist es oft zweckmäßig, den Exponentiation-Operator ( ** ) mit fraktionellen Exponenten zu verwenden, um n-te math.sqrt auszuführen, wie z.

Die Umkehrung einer Exponentiation ist die Exponentiation durch den Kehrwert des Exponenten. Wenn Sie also eine Zahl würfeln können, indem Sie sie auf den Exponenten von 3 setzen, können Sie die Kubikwurzel einer Zahl finden, indem Sie sie auf den Exponenten von 1/3 setzen.

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

Berechnen großer ganzzahliger Wurzeln

Auch wenn Python nativ große Ganzzahlen unterstützt, kann die Verwendung der n-ten Wurzel sehr großer Zahlen in Python fehlschlagen.

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

OverflowError: long int zu groß, um in Float konvertiert zu werden

Wenn Sie mit solchen großen Ganzzahlen arbeiten, müssen Sie eine benutzerdefinierte Funktion verwenden, um die n-te Wurzel einer Zahl zu berechnen.

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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow