Python - abs vs fabs


107

Ho notato che in Python esistono due metodi di ricerca simili per trovare il valore assoluto di un numero:

Primo

abs(-5)

Secondo

import math
math.fabs(-5)

In cosa differiscono questi metodi?

Risposte:


127

math.fabs()converte il suo argomento in float se può (se non può, lancia un'eccezione). Quindi prende il valore assoluto e restituisce il risultato come float.

Oltre ai float, abs()funziona anche con interi e numeri complessi. Il tipo restituito dipende dal tipo del suo argomento.

In [7]: type(abs(-2))
Out[7]: int

In [8]: type(abs(-2.0))
Out[8]: float

In [9]: type(abs(3+4j))
Out[9]: float

In [10]: type(math.fabs(-2))
Out[10]: float

In [11]: type(math.fabs(-2.0))
Out[11]: float

In [12]: type(math.fabs(3+4j))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/npe/<ipython-input-12-8368761369da> in <module>()
----> 1 type(math.fabs(3+4j))

TypeError: can't convert complex to float

4
absfunziona con molto di più che solo interi e float, e il tipo di risultato non è sempre lo stesso dell'argomento, ad es abs(3+4j).
agf

1
aggiungi un commento su come fabsimpiegare più tempo a causa della sua natura sempre fluttuante e hai la risposta giusta!
Patrick Perini

@agf: Grazie per avermi ricordato i numeri complessi. Per interesse, quali altre classi di cose possono __builtin__.abs()essere applicate con successo?
NPE

5
@aix Qualsiasi classe definita dall'utente che definisce il __abs__metodo magico
agf

9

Modifica: come suggerito da @aix, un modo migliore (più equo) per confrontare la differenza di velocità:

In [1]: %timeit abs(5)
10000000 loops, best of 3: 86.5 ns per loop

In [2]: from math import fabs

In [3]: %timeit fabs(5)
10000000 loops, best of 3: 115 ns per loop

In [4]: %timeit abs(-5)
10000000 loops, best of 3: 88.3 ns per loop

In [5]: %timeit fabs(-5)
10000000 loops, best of 3: 114 ns per loop

In [6]: %timeit abs(5.0)
10000000 loops, best of 3: 92.5 ns per loop

In [7]: %timeit fabs(5.0)
10000000 loops, best of 3: 93.2 ns per loop

In [8]: %timeit abs(-5.0)
10000000 loops, best of 3: 91.8 ns per loop

In [9]: %timeit fabs(-5.0)
10000000 loops, best of 3: 91 ns per loop

Quindi sembra abs()che abbia solo un leggero vantaggio di velocità rispetto fabs()agli interi. Per i galleggianti abs()e fabs()dimostrare una velocità simile.


Oltre a quanto ha detto @aix, un'altra cosa da considerare è la differenza di velocità:

In [1]: %timeit abs(-5)
10000000 loops, best of 3: 102 ns per loop

In [2]: import math

In [3]: %timeit math.fabs(-5)
10000000 loops, best of 3: 194 ns per loop

Quindi abs()è più veloce di math.fabs().


3
Non stai paragonando le mele alle mele lì. Usalo from math import fabsdi sicuro e prova -5.0per entrambi.
agf

Anche risultati di tempistica inaffidabili? Prima avevi addominali (-5) a 102 ns, poi lo hai mostrato come 88,3 ns. Non trarre mai conclusioni da una singola esecuzione di un benchmark, anche se internamente cerca di evitare i problemi come fa il tempo.
Peter Hansen

1
Altri due punti: questo confronta ancora mele e arance, poiché abs viene cercato nei builtin, mentre fabs è nello spazio dei nomi del modulo. Fai "xabs = abs" quindi xabs (num) per rimuovere l'effetto. Inoltre, con Python 3.2 le cose cambiano parecchio e apparentemente abs () è un po 'più veloce (> 2x), almeno su float.
Peter Hansen

1
@PeterHansen Hai ragione, quelli provengono da due esecuzioni con carichi di sistema diversi. Anche se confrontata all'interno della stessa serie di test, la differenza relativa è ancora valida. Inoltre, grazie per aver sottolineato la differenza dello spazio dei nomi - non l'ho considerato. Non l'ho provato su 3.2, ma è buono a sapersi! Aggiornerò la mia risposta con i tuoi suggerimenti un po 'più tardi :) Grazie ancora!
KZ

3

math.fabs()restituisce sempre float, mentre abs()può restituire un numero intero.


6
abspuò restituire qualsiasi tipo, a seconda del __abs__metodo speciale del tipo su cui viene chiamato.
agf

0

abs(): Restituisce il valore assoluto secondo l'argomento, cioè se l'argomento è int, restituisce int, se l'argomento è float restituisce float. Inoltre funziona anche su variabili complesse, cioè abs(a+bj)funziona anche e restituisce un valore assoluto, ad esmath.sqrt(((a)**2)+((b)**2)

math.fabs(): Funziona solo su valori interi o float. Restituisce sempre il valore float assoluto indipendentemente dal tipo di argomento (ad eccezione dei numeri complessi).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.