2013-09-23 13 views
48

Nel mio campo è molto comune raggruppare alcuni numeri, gestirli insieme e ottenere la radice quadrata del risultato. Questo è fatto nel teorema di Pitagora, e il calcolo RMS, per esempio.Esponenziazione in Python - dovrei preferire l'operatore ** invece di math.pow e math.sqrt?

In NumPy, ho fatto quanto segue:

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

E in pitone qualcosa di puro come questo ci si aspetterebbe:

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

Tuttavia, ho utilizzato questa forma di pitone pura, dal momento che Lo trovo molto più compatto, indipendente dall'importazione e apparentemente equivalente:

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

Ho sentito alcune persone sostengono che l'operatore ** è una sorta di hack e che la quadratura di un numero esponentandolo da 0.5 non è così leggibile. Ma quello che vorrei chiedere è se:

"C'è qualche ragione COMPUTAZIONALE per preferire le due precedenti alternative rispetto alla terza (s)?"

Grazie per la lettura!

+1

Questa potrebbe essere una discussione pertinente - http://stackoverflow.com/questions/327002/which-is-faster-in-python-x-5-or-math-sqrtx –

+1

Tendo pensare che math.sqrt() sia più leggibile di() ** 0.5. –

+1

@Maxime, vorrei andare avanti e usare semplicemente 'sqrt' con' da math import sqrt'. –

risposta

43

math.sqrt è l'implementazione C di radice quadrata ed è quindi diverso dall'utilizzo dell'operatore ** che implementa la funzione incorporata di Python pow. Pertanto, l'utilizzo di math.sqrt dà effettivamente una risposta diversa rispetto all'utilizzo dell'operatore ** e vi è effettivamente un motivo computazionale per preferire l'implementazione del modulo numpy o math tramite il built-in. In particolare, le funzioni sqrt sono probabilmente implementate nel modo più efficiente possibile mentre ** opera su un numero elevato di basi ed esponenti ed è probabilmente non ottimizzato per il caso specifico della radice quadrata. D'altra parte, la funzione integrata pow gestisce alcuni casi extra come "numeri complessi, potenze di numeri illimitati ed esponenziazione modulare".

See this Stack Overflow question for more information on the difference between ** and math.sqrt.

In termini di che è più "Pythonic", penso che abbiamo bisogno di discutere la definizione di questa parola. Da the official Python glossary, afferma che un pezzo di codice o idea è Pythonic se "segue da vicino gli idiomi più comuni del linguaggio Python, piuttosto che implementare il codice usando concetti comuni ad altri linguaggi."In ogni altra lingua a cui riesco a pensare, c'è un modulo matematico con funzioni radice quadrate di base, tuttavia ci sono linguaggi privi di un operatore di potenza come ** ad esempio C++. Quindi ** è probabilmente più Pythonic, ma se sia o non sia oggettivamente migliore dipende dal caso d'uso

+0

Dove entra in funzione 'operator.pow'? –

+0

Ottima risposta, in particolare per prendere quella che poteva essere una discussione altamente 'supponente' e focalizzarsi sull'OP, così come sui tenant essenziali di Python. Complimenti. – GrayedFox

+0

Tuttavia, se gli input sono interi, ** o la funzione di pow incorporata può essere preferibile computazionalmente: "A differenza dell'operatore integrato **, math.pow() converte entrambi i suoi argomenti in" float ". Usa ** o la funzione incorporata di pow() per calcolare i poteri interi esatti. " - Documenti Python: libreria matematica https://docs.python.org/2/library/math.html#power-and-logarithmic-functions – hyperGeoMetric

12

Anche in Python di base si può fare il calcolo in forma generica

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

x ** 2 non è sicuramente un mod e il calcolo eseguito è la stessa (ho controllato con il codice sorgente CPython). In realtà lo trovo più leggibile (e la leggibilità conta).

Utilizzare invece x ** 0.5 per eseguire la radice quadrata non esegue esattamente lo stesso calcolo di math.sqrt poiché il primo (probabilmente) viene calcolato utilizzando i logaritmi e il secondo (probabilmente) utilizzando l'istruzione numerica specifica del processore matematico.

Io uso spesso x ** 0.5 semplicemente perché non desidero aggiungere math solo per quello. Mi aspetterei comunque un'istruzione specifica per la radice quadrata di lavorare meglio (più precisamente) di un'operazione multi-passo con logaritmi.

+2

Apparentemente [nessuno dei due è più preciso] (http://stackoverflow.com/a/842358/199360) - ma [sqrt è più veloce] (http://stackoverflow.com/a/327011/199360). – adib

+0

Perché l'interprete Python non riconosce x ** 0.5 come caso speciale? Dopotutto lo 0,5 è una costante. – user3150208

Problemi correlati