Python Language
Potenzierung
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
oderfloat < 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