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 of float < 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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow