Sök…


Syntax

  • värde1 ** värde2
  • pow (värde1, värde2 [, värde3])
  • värde1 .__ pow __ (värde2 [, värde3])
  • värde2 .__ rpow __ (värde1)
  • operator.pow (värde1, värde2)
  • operatör .__ pow __ (värde1, värde2)
  • math.pow (värde1, värde2)
  • math.sqrt (värde1)
  • math.exp (värde1)
  • cmath.exp (värde1)
  • math.expm1 (värde1)

Fyrkantig rot: matematik.sqrt () och cmath.sqrt

math innehåller math.sqrt() -funktionen som kan beräkna kvadratroten av valfritt nummer (som kan konverteras till en float ) och resultatet kommer alltid att vara en float :

import math

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

math.sqrt() höjer en ValueError om resultatet skulle vara complex :

math.sqrt(-10)              

ValueError: fel i matematisk domän

math.sqrt(x) är snabbare än math.pow(x, 0.5) eller x ** 0.5 men resultatens precision är densamma. cmath modulen är mycket lik math , förutom att den kan beräkna komplexa siffror och alla resultat är i form av en + bi. Den kan också använda .sqrt() :

import cmath

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

Vad är det med j ? j motsvarar kvadratroten -1. Alla siffror kan placeras i formen a + bi, eller i detta fall, en + bj. a är den verkliga delen av antalet som 2 i 2+0j . Eftersom den inte har någon imaginär del, är b 0. b representerar en del av den imaginära delen av antalet som 2 i 2j . Eftersom det inte finns någon riktig del i detta kan 2j också skrivas som 0 + 2j .

Exponentiering med inbyggda: ** och pow ()

Exponentiering kan användas med hjälp av den inbyggda pow funktionen eller ** -operatören:

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

För de flesta (alla i Python 2.x) aritmetiska operationer blir resultatet typ av den bredare operanden. Detta är inte sant för ** ; Följande fall är undantag från denna regel:

  • Bas: int , exponent: int < 0 :

    2 ** -3
    # Out: 0.125 (result is a float)
    
  • Detta gäller också för Python 3.x.

  • Innan Python 2.2.0 höjde detta en ValueError .

  • Bas: int < 0 eller float < 0 , exponent: float != int

    (-2) ** (0.5)  # also (-2.) ** (0.5)    
    # Out: (8.659560562354934e-17+1.4142135623730951j) (result is complex)
    
  • Innan python 3.0.0 höjde detta en ValueError .

operator innehåller två funktioner som motsvarar ** -operatören:

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

eller man kan direkt ringa __pow__ metoden:

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)   

Exponentiering med matematikmodulen: math.pow ()

Den math -modul innehåller en annan math.pow() funktion. Skillnaden med den inbyggda pow() -funktionen eller ** -operatören är att resultatet alltid är en float :

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

Som utesluter beräkningar med komplexa ingångar:

math.pow(2, 2+0j) 

TypeError: kan inte konvertera komplex till float

och beräkningar som skulle leda till komplexa resultat:

math.pow(-2, 0.5)

ValueError: fel i matematisk domän

Exponentiell funktion: math.exp () och cmath.exp ()

Både math och cmath modulen innehåller Euler-numret: e och att använda det med den inbyggda pow() -funktionen eller ** -operatör fungerar mestadels som 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)

Resultatet är emellertid annorlunda och att använda exponentiell funktion direkt är mer pålitlig än inbyggd exponentiering med math.e :

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

Exponentiell funktion minus 1: math.expm1 ()

math innehåller expm1() -funktionen som kan beräkna uttrycket math.e ** x - 1 för mycket små x med högre precision än math.exp(x) eller cmath.exp(x) skulle tillåta:

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

För mycket små x blir skillnaden större:

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

Förbättringen är betydande i vetenskaplig datoranvändning. Till exempel innehåller Plancks lag en exponentiell funktion 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
#                                      ^------------

Magiska metoder och exponentiering: inbyggd, matematik och cmath

Antar att du har en klass som lagrar rent heltal:

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)

Använda den inbyggda pow funktionen eller ** __pow__ ringer alltid __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__

Det andra argumentet för __pow__() kan endast tillhandahållas genom att använda det inbyggda pow() eller genom att direkt anropa metoden:

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

Medan math alltid konverterar den till en float och använder floatberäkningen:

import math

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

cmath funktioner försöker konvertera det till complex men kan också falla tillbaka till att float om det inte finns någon uttrycklig konvertering till 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__

Varken math eller cmath fungerar om också __float__() -metoden saknas:

del Integer.__float__  # Deleting __complex__ method

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

TypeError: en flottör krävs

Modular exponentiation: pow () med 3 argument

Att tillhandahålla pow() med 3 argument pow(a, b, c) utvärderar den modulära exponentieringen a b mod c :

pow(3, 4, 17)   # 13

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

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

För inbyggda typer som använder modulär exponentiering är det bara möjligt om:

  • Det första argumentet är ett int
  • Det andra argumentet är ett int >= 0
  • Tredje argumentet är ett int != 0

Dessa begränsningar finns också i python 3.x

Till exempel kan man använda 3-argumentformen för pow att definiera en modulär invers funktion:

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]

Rötter: nth-rot med fraktionella exponenter

Medan math.sqrt funktionen tillhandahålls för det specifika fallet med fyrkantiga rötter, är det ofta bekvämt att använda exponentiation-operatören ( ** ) med fraktionella exponenter för att utföra nth-root-operationer, som kubrot.

Det inverse av en exponentiering är exponentiering genom exponentens ömsesidiga. Så om du kan kubera ett nummer genom att sätta det till exponenten för 3, kan du hitta kubroten till ett nummer genom att sätta det till exponenten på 1/3.

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

Beräkna stora heltalrötter

Även om Python naturligtvis stöder stora heltal kan det hända att Python misslyckas med att få den första roten till mycket stora antal.

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

OverflowError: lång int för stor för att konvertera till float

När du hanterar så stora heltal måste du använda en anpassad funktion för att beräkna den n: a roten till ett nummer.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow