Python Language
machtsverheffen
Zoeken…
Syntaxis
- waarde1 ** waarde2
- pow (waarde1, waarde2 [, waarde3])
- waarde1 .__ pow __ (waarde2 [, waarde3])
- value2 rpow .__ __ (waarde1)
- operator.pow (waarde1, waarde2)
- operator .__ pow __ (waarde1, waarde2)
- math.pow (waarde1, waarde2)
- math.sqrt (waarde1)
- math.exp (waarde1)
- cmath.exp (waarde1)
- math.expm1 (waarde1)
Vierkantswortel: math.sqrt () en cmath.sqrt
De math
bevat de functie math.sqrt()
die de vierkantswortel van een willekeurig getal kan berekenen (die kan worden geconverteerd naar een float
) en het resultaat zal altijd een float
:
import math
math.sqrt(9) # 3.0
math.sqrt(11.11) # 3.3331666624997918
math.sqrt(Decimal('6.25')) # 2.5
De functie math.sqrt()
verhoogt een ValueError
als het resultaat complex
zou zijn:
math.sqrt(-10)
ValueError: wiskundige domeinfout
math.sqrt(x)
is sneller dan math.pow(x, 0.5)
of x ** 0.5
maar de precisie van de resultaten is hetzelfde. De cmath
module lijkt erg op de math
, behalve dat deze complexe getallen kan berekenen en alle resultaten de vorm hebben van een + bi. Het kan ook .sqrt()
:
import cmath
cmath.sqrt(4) # 2+0j
cmath.sqrt(-4) # 2j
Wat is er met de j
? j
is het equivalent van de vierkantswortel van -1. Alle getallen kunnen in de vorm a + bi worden geplaatst, of in dit geval a + bj. a
is het reële deel van het getal zoals de 2 in 2+0j
. Omdat het geen imaginair deel heeft, is b
0. b
vertegenwoordigt een deel van het imaginaire deel van het getal zoals de 2 in 2j
. Aangezien hier geen echt deel aan is, kan 2j
ook worden geschreven als 0 + 2j
.
Exponentiatie met ingebouwde: ** en pow ()
Exponentiatie kan worden gebruikt met behulp van de ingebouwde pow
of de **
operator:
2 ** 3 # 8
pow(2, 3) # 8
Voor de meeste (allemaal in Python 2.x) rekenkundige bewerkingen is het type resultaat dat van de bredere operand. Dit geldt niet voor **
; de volgende gevallen zijn uitzonderingen op deze regel:
Base:
int
, exponent:int < 0
:2 ** -3 # Out: 0.125 (result is a float)
Dit is ook geldig voor Python 3.x.
Vóór Python 2.2.0 leverde dit een
ValueError
.Base:
int < 0
offloat < 0
, exponent:float != int
(-2) ** (0.5) # also (-2.) ** (0.5) # Out: (8.659560562354934e-17+1.4142135623730951j) (result is complex)
Vóór python 3.0.0 leverde dit een
ValueError
.
De operator
bevat twee functies die equivalent zijn aan de **
-operator:
import operator
operator.pow(4, 2) # 16
operator.__pow__(4, 3) # 64
of men zou direct de __pow__
methode __pow__
aanroepen:
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)
Exponentiatie met de wiskundemodule: math.pow ()
De math
module bevat nog een functie math.pow()
. Het verschil met de ingebouwde pow()
-functie of **
operator is dat het resultaat altijd een float
:
import math
math.pow(2, 2) # 4.0
math.pow(-2., 2) # 4.0
Welke berekeningen met complexe ingangen uitsluit:
math.pow(2, 2+0j)
TypeError: kan complex niet naar float converteren
en berekeningen die tot complexe resultaten zouden leiden:
math.pow(-2, 0.5)
ValueError: wiskundige domeinfout
Exponentiële functie: math.exp () en cmath.exp ()
Zowel de math
als de cmath
module bevatten het Euler-nummer: e en het gebruik ervan met de ingebouwde pow()
-functie of **
-operator werkt meestal als 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)
Het resultaat is echter anders en het direct gebruiken van de exponentiële functie is betrouwbaarder dan ingebouwde exponentiatie met math.e
:
print(math.e ** 10) # 22026.465794806703
print(math.exp(10)) # 22026.465794806718
print(cmath.exp(10).real) # 22026.465794806718
# difference starts here ---------------^
Exponentiële functie min 1: math.expm1 ()
De math
bevat de functie expm1()
die de uitdrukking math.e ** x - 1
kan berekenen voor zeer kleine x
met een grotere precisie dan math.exp(x)
of cmath.exp(x)
zou toestaan:
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
# ------------------^
Voor heel kleine x wordt het verschil groter:
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
# ^-------------------
De verbetering is aanzienlijk in wetenschappelijk computergebruik. De wet van Planck bevat bijvoorbeeld een exponentiële functie 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 en exponentiatie: ingebouwd, wiskunde en cmath
Stel dat u een klasse hebt die puur gehele waarden opslaat:
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)
Gebruik de ingebouwde pow
functie of **
operator altijd __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__
Het tweede argument van de __pow__()
-methode kan alleen worden geleverd met behulp van de build- pow()
of door de methode rechtstreeks aan te roepen:
pow(Integer(2), 3, 4) # Integer(0)
# Prints: Using __pow__ with modulo
Integer(2).__pow__(3, 4) # Integer(0)
# Prints: Using __pow__ with modulo
Terwijl de math
functies het altijd omzetten in een float
en de float-berekening gebruiken:
import math
math.pow(Integer(2), 0.5) # 1.4142135623730951
# Prints: Using __float__
cmath
-functies proberen het om te zetten naar complex
maar kunnen ook terugvallen op float
als er geen expliciete conversie naar 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__
math
noch cmath
zal werken als ook de __float__()
-methode ontbreekt:
del Integer.__float__ # Deleting __complex__ method
math.sqrt(Integer(2)) # also cmath.exp(Integer(2))
TypeError: een vlotter is vereist
Modulaire exponentiatie: pow () met 3 argumenten
pow()
voorzien van 3 argumenten pow(a, b, c)
evalueert de modulaire exponentiatie a b mod c :
pow(3, 4, 17) # 13
# equivalent unoptimized expression:
3 ** 4 % 17 # 13
# steps:
3 ** 4 # 81
81 % 17 # 13
Voor ingebouwde typen is het gebruik van modulaire exponentiatie alleen mogelijk als:
- Het eerste argument is een
int
- Tweede argument is een
int >= 0
- Het derde argument is een
int != 0
Deze beperkingen zijn ook aanwezig in python 3.x
Men kan bijvoorbeeld de 3-argumentvorm van pow
gebruiken om een modulaire inverse functie te definiëren:
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]
Roots: nth-root met fractionele exponenten
Hoewel de functie math.sqrt
is voor het specifieke geval van vierkantswortels, is het vaak handig om de exponentiatie-operator ( **
) met fractionele exponenten te gebruiken om nde-rootbewerkingen uit te voeren, zoals kubuswortels.
Het omgekeerde van een exponentiatie is exponentiatie door de wederkerigheid van de exponent. Dus, als je een getal kunt kuberen door het naar de exponent van 3 te brengen, kun je de kubuswortel van een getal vinden door het naar de exponent van 1/3 te brengen.
>>> x = 3
>>> y = x ** 3
>>> y
27
>>> z = y ** (1.0 / 3)
>>> z
3.0
>>> z == x
True
Grote gehele wortels berekenen
Hoewel Python native grote gehele getallen ondersteunt, kan het nemen van de nde wortel van zeer grote aantallen in Python mislukken.
x = 2 ** 100
cube = x ** 3
root = cube ** (1.0 / 3)
OverflowError: lang int te groot om te converteren naar zwevend
Wanneer u met dergelijke grote gehele getallen omgaat, moet u een aangepaste functie gebruiken om de nde wortel van een getal te berekenen.
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