Python Language
Potęgowanie
Szukaj…
Składnia
- wartość1 ** wartość2
- pow (wartość1, wartość2 [, wartość3])
- wartość1 .__ pow __ (wartość2 [, wartość3])
- wartość2 .__ rpow __ (wartość1)
- operator.pow (wartość1, wartość2)
- operator .__ pow __ (wartość1, wartość2)
- matematyka.pow (wartość1, wartość2)
- math.sqrt (wartość1)
- math.exp (wartość1)
- cmath.exp (wartość1)
- math.expm1 (wartość1)
Pierwiastek kwadratowy: math.sqrt () i cmath.sqrt
Moduł math zawiera funkcję math.sqrt() która może obliczyć pierwiastek kwadratowy z dowolnej liczby (którą można przekształcić w liczbę float ), a wynikiem będzie zawsze liczba float :
import math
math.sqrt(9) # 3.0
math.sqrt(11.11) # 3.3331666624997918
math.sqrt(Decimal('6.25')) # 2.5
Funkcja math.sqrt() wywołuje błąd ValueError jeśli wynik byłby complex :
math.sqrt(-10)
ValueError: błąd domeny matematycznej
math.sqrt(x) jest szybszy niż math.pow(x, 0.5) lub x ** 0.5 ale dokładność wyników jest taka sama. Moduł cmath jest bardzo podobny do modułu math , z wyjątkiem tego, że może obliczać liczby zespolone, a wszystkie jego wyniki są w postaci + bi. Może także używać .sqrt() :
import cmath
cmath.sqrt(4) # 2+0j
cmath.sqrt(-4) # 2j
O co chodzi z tym j ? j jest ekwiwalentem pierwiastka kwadratowego z -1. Wszystkie liczby można nadać postaci a + bi lub w tym przypadku a + bj. a jest prawdziwą częścią liczby, np. 2 w 2+0j . Ponieważ nie ma części urojonej, b wynosi 0. b reprezentuje część urojonej części liczby, takiej jak 2 w 2j . Ponieważ nie ma w tym prawdziwej roli, 2j można również zapisać jako 0 + 2j .
Potęgowanie za pomocą wbudowanych funkcji: ** i pow ()
Potęgowanie można zastosować za pomocą wbudowanej funkcji pow lub operatora ** :
2 ** 3 # 8
pow(2, 3) # 8
W przypadku większości operacji arytmetycznych (wszystko w Pythonie 2.x) typem wyniku będzie szerszy operand. Nie dotyczy to ** ; następujące przypadki są wyjątkami od tej reguły:
Podstawa:
int, wykładnik:int < 0:2 ** -3 # Out: 0.125 (result is a float)Dotyczy to również Pythona 3.x.
Przed wersją Python 2.2.0 powodowało to błąd
ValueError.Podstawa:
int < 0lubfloat < 0, wykładnik:float != int(-2) ** (0.5) # also (-2.) ** (0.5) # Out: (8.659560562354934e-17+1.4142135623730951j) (result is complex)Przed Pythonem 3.0.0 wywołało to błąd
ValueError.
Moduł operator zawiera dwie funkcje równoważne z operator ** :
import operator
operator.pow(4, 2) # 16
operator.__pow__(4, 3) # 64
lub można bezpośrednio wywołać metodę __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)
Potęgowanie za pomocą modułu matematycznego: math.pow ()
Moduł math zawiera inną math.pow() . Różnica w stosunku do wbudowanej funkcji pow() lub operatora ** polega na tym, że wynikiem jest zawsze liczba float :
import math
math.pow(2, 2) # 4.0
math.pow(-2., 2) # 4.0
Co wyklucza obliczenia o złożonych danych wejściowych:
math.pow(2, 2+0j)
TypeError: nie można przekonwertować złożonego na zmiennoprzecinkowy
oraz obliczenia, które doprowadziłyby do złożonych wyników:
math.pow(-2, 0.5)
ValueError: błąd domeny matematycznej
Funkcja wykładnicza: math.exp () i cmath.exp ()
Zarówno cmath math i cmath zawierają numer Euler: e, a użycie go z wbudowaną funkcją pow() lub ** -operator działa głównie jak 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)
Jednak wynik jest inny i bezpośrednie użycie funkcji wykładniczej jest bardziej niezawodne niż wbudowane potęgowanie z podstawową math.e :
print(math.e ** 10) # 22026.465794806703
print(math.exp(10)) # 22026.465794806718
print(cmath.exp(10).real) # 22026.465794806718
# difference starts here ---------------^
Funkcja wykładnicza minus 1: matematyka.expm1 ()
Moduł math zawiera funkcję expm1() która może obliczyć wyrażenie math.e ** x - 1 dla bardzo małego x z większą precyzją niż math.exp(x) lub cmath.exp(x) pozwoli:
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
# ------------------^
Dla bardzo małego x różnica staje się większa:
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
# ^-------------------
Poprawa jest znacząca w informatyce naukowej. Na przykład prawo Plancka zawiera funkcję wykładniczą 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
# ^------------
Magiczne metody i potęgowanie: wbudowane, matematyczne i cmath
Załóżmy, że masz klasę, która przechowuje wartości całkowite:
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)
Korzystanie z wbudowanej funkcji pow lub ** operator zawsze wywołuje __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__
Drugi argument metody __pow__() można podać tylko za pomocą wbudowanej funkcji pow() lub bezpośrednio wywołując metodę:
pow(Integer(2), 3, 4) # Integer(0)
# Prints: Using __pow__ with modulo
Integer(2).__pow__(3, 4) # Integer(0)
# Prints: Using __pow__ with modulo
Podczas gdy funkcje math zawsze konwertują go na float i używają obliczeń zmiennoprzecinkowych:
import math
math.pow(Integer(2), 0.5) # 1.4142135623730951
# Prints: Using __float__
cmath próbuje przekonwertować go na complex ale może również powrócić do stanu float jeśli nie ma wyraźnej konwersji na 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__
Ani math ani cmath nie będą działać, jeśli brakuje również metody __float__() :
del Integer.__float__ # Deleting __complex__ method
math.sqrt(Integer(2)) # also cmath.exp(Integer(2))
TypeError: wymagana jest liczba zmiennoprzecinkowa
Modułowe potęgowanie: pow () z 3 argumentami
Dostarczenie pow() z 3 argumentami pow(a, b, c) ocenia modułowe potęgowanie a b mod c :
pow(3, 4, 17) # 13
# equivalent unoptimized expression:
3 ** 4 % 17 # 13
# steps:
3 ** 4 # 81
81 % 17 # 13
W przypadku typów wbudowanych wykorzystujących potęgowanie modułowe jest możliwe tylko wtedy, gdy:
- Pierwszy argument to
int - Drugi argument to
int >= 0 - Trzeci argument to
int != 0
Te ograniczenia są również obecne w Pythonie 3.x
Na przykład można użyć 3-argumentowej formy pow aby zdefiniować modułową funkcję odwrotną :
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]
Korzenie: n-ty korzeń z wykładnikami ułamkowymi
Chociaż funkcja math.sqrt jest dostępna dla konkretnego przypadku pierwiastków kwadratowych, często wygodnie jest używać operatora potęgowania ( ** ) z potęgami ułamkowymi do wykonywania operacji n-tego pierwiastka, takich jak pierwiastki kostne.
Odwrotnością potęgowania jest potęgowanie przez odwrotność potęgi. Tak więc, jeśli możesz kostkować liczbę, umieszczając ją na wykładniku 3, możesz znaleźć pierwiastek kostki z liczby, umieszczając ją na wykładniku 1/3.
>>> x = 3
>>> y = x ** 3
>>> y
27
>>> z = y ** (1.0 / 3)
>>> z
3.0
>>> z == x
True
Obliczanie korzeni dużej liczby całkowitej
Mimo że Python natywnie obsługuje duże liczby całkowite, n-ty pierwiastek bardzo dużych liczb może zawieść w Pythonie.
x = 2 ** 100
cube = x ** 3
root = cube ** (1.0 / 3)
OverflowError: long int jest zbyt duży, aby go przekonwertować na float
W przypadku tak dużych liczb całkowitych konieczne będzie użycie funkcji niestandardowej w celu obliczenia n-tego pierwiastka z liczby.
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