Exponentiatie in Python – moet ik de ** operator verkiezen in plaats van math.pow en math.sqrt?

In mijn vakgebied is het heel gebruikelijk om een ​​aantal getallen te kwadrateren, ze samen te werken en de vierkantswortel van het resultaat te nemen. Dit wordt gedaan in de stelling van Pythagoras, en de RMS-berekening, bijvoorbeeld.

In numpy heb ik het volgende gedaan:

result = numpy.sqrt(numpy.sum(numpy.pow(some_vector, 2)))

En in pure python zou zoiets als dit worden verwacht:

result = math.sqrt(math.pow(A, 2) + math.pow(B,2)) # example with two dimensions.

Ik gebruik echter deze pure python-vorm, omdat ik deze veel compacter, importonafhankelijk en schijnbaar gelijkwaardig vind:

result = (A**2 + B**2)**0.5   # two dimensions
result = (A**2 + B**2 + C**2 + D**2)**0.5

Ik heb gehoord dat sommige mensen beweren dat de operator **een soort hack is, en dat het kwadrateren van een getal door het te exponentiëren met 0.5niet zo leesbaar is. Maar wat ik zou willen vragen is of:

“Is er een COMPUTATIONELE reden om de eerste twee alternatieven te verkiezen boven de derde(n)?”

Bedankt voor het lezen!


Antwoord 1, autoriteit 100%

math.sqrtis de C-implementatie van vierkantswortel en verschilt daarom van het gebruik van de **-operator die de ingebouwde powfunctie. Het gebruik van math.sqrtgeeft dus eigenlijk een ander antwoord dan het gebruik van de operator **en er is inderdaad een rekenkundige reden om de voorkeur te geven aan numpyof mathmodule implementatie over de ingebouwde. Specifiek zijn de sqrt-functies waarschijnlijk op de meest efficiënte manier geïmplementeerd, terwijl **werkt over een groot aantal basen en exponenten en waarschijnlijk niet geoptimaliseerd is voor het specifieke geval van vierkantswortel. Aan de andere kant verwerkt de ingebouwde functie poween paar extra gevallen zoals “complexe getallen, onbegrensde gehele machten en modulaire machtsverheffing”.

Bekijk deze Stack Overflow-vraag voor meer informatie over het verschil tussen **en math.sqrt.

In termen van wat meer “pythonisch” is, denk ik dat we de definitie van dat woord moeten bespreken. Uit de officiële Python-woordenlijststaat dat een stukje code of idee is Pythonic als het “de meest voorkomende idiomen van de Python-taal nauwgezet volgt, in plaats van code te implementeren met behulp van concepten die gebruikelijk zijn in andere talen.” In elke andere taal die ik kan bedenken, is er een wiskundige module met elementaire vierkantswortelfuncties. Er zijn echter talen die geen power-operator hebben, zoals **b.v. C++. Dus **is waarschijnlijk meer Pythonisch, maar of het objectief beter is, hangt af van het gebruik.


Antwoord 2, autoriteit 31%

Zelfs in basis Python kun je de berekening in generieke vorm doen

result = sum(x**2 for x in some_vector) ** 0.5

x ** 2is zeker geen hack en de uitgevoerde berekening is hetzelfde (ik heb het gecontroleerd met de cpython-broncode). Ik vind het eigenlijk beter leesbaar (en leesbaarheid telt).

In plaats daarvan x ** 0.5gebruiken om de vierkantswortel te nemen, doet niet exact dezelfde berekeningen als math.sqrt, aangezien de eerste (waarschijnlijk) wordt berekend met logaritmen en de laatste (waarschijnlijk) met behulp van de specifieke numerieke instructie van de wiskundige processor.

Ik gebruik vaak x ** 0.5simpelweg omdat ik daar niet alleen mathvoor wil toevoegen. Ik zou echter verwachten dat een specifieke instructie voor de vierkantswortel beter (nauwkeuriger) werkt dan een meerstapsbewerking met logaritmen.

Other episodes