Python - abs vs fabs

107

Saya perhatikan bahwa di python ada dua metode pencarian serupa untuk menemukan nilai absolut sebuah angka:

Pertama

abs(-5)

Kedua

import math
math.fabs(-5)

Apa perbedaan metode ini?

Mateusz Jagiełło
sumber

Jawaban:

127

math.fabs()mengonversi argumennya menjadi float jika bisa (jika tidak bisa, itu melontarkan pengecualian). Kemudian mengambil nilai absolut, dan mengembalikan hasilnya sebagai pelampung.

Selain pelampung, abs()juga berfungsi dengan bilangan bulat dan bilangan kompleks. Jenis kembaliannya bergantung pada jenis argumennya.

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
NPE
sumber
4
absbekerja dengan lebih dari sekedar integer dan float, dan jenis hasil tidak selalu sama dengan argumennya, misalnya abs(3+4j).
agf
1
tambahkan komentar tentang fabsmengambil lebih lama karena sifatnya yang selalu mengambang dan Anda mendapat jawaban yang benar!
Patrick Perini
@agf: Terima kasih telah mengingatkan saya tentang bilangan kompleks. Karena minat, kelas hal lain apa yang dapat __builtin__.abs()diterapkan dengan sukses?
NPE
5
@aix Setiap kelas yang ditentukan pengguna yang mendefinisikan __abs__metode ajaib
agf
9

Edit: seperti yang disarankan @aix, cara yang lebih baik (lebih adil) untuk membandingkan perbedaan kecepatan:

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

Jadi tampaknya abs()hanya memiliki sedikit keunggulan kecepatan dibandingkan fabs()bilangan bulat. Untuk pelampung, abs()dan fabs()menunjukkan kecepatan yang sama.


Selain apa yang dikatakan @aix, satu hal lagi yang perlu dipertimbangkan adalah perbedaan kecepatan:

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

Jadi abs()lebih cepat dari math.fabs().

KZ
sumber
3
Anda tidak membandingkan apel dengan apel di sana. Gunakan from math import fabsdengan pasti, dan coba -5.0untuk keduanya.
agf
Hasil waktu juga tidak dapat diandalkan? Anda pertama kali memiliki abs (-5) di 102ns, kemudian menunjukkannya sebagai 88.3ns. Jangan pernah menarik kesimpulan dari satu kali menjalankan tolok ukur apa pun, meskipun secara internal mencoba untuk menghindari masalah seperti halnya waktu.
Peter Hansen
1
Dua poin lagi: ini masih membandingkan apel dan jeruk, karena abs dicari di builtins, sementara fabs ada di namespace modul. Lakukan "xabs = abs" lalu xabs (num) untuk menghilangkan efek itu. Juga, dengan Python 3.2 banyak hal berubah sedikit dan tampaknya abs () sedikit lebih cepat (> 2x), setidaknya pada float.
Peter Hansen
1
@PeterHansen Anda benar, mereka berasal dari dua proses di bawah beban sistem yang berbeda. Meskipun jika dibandingkan dalam rangkaian pengujian yang sama, perbedaan relatifnya masih valid. Juga, terima kasih telah menunjukkan perbedaan namespace - saya tidak mempertimbangkan itu. Saya belum mencobanya di 3.2, tapi itu bagus untuk diketahui! Saya akan memperbarui jawaban saya dengan saran Anda nanti :) Terima kasih lagi!
KZ
3

math.fabs()selalu mengembalikan float, sementara abs()mungkin mengembalikan integer.

Tadeck
sumber
6
absdapat mengembalikan tipe apa pun, bergantung pada __abs__metode khusus dari tipe yang dipanggil.
agf
0

abs(): Mengembalikan nilai absolut sesuai argumen, yaitu jika argumen int maka mengembalikan int, jika argumen mengambang, ia mengembalikan float. Juga bekerja pada variabel kompleks juga yaitu abs(a+bj)bekerja dan mengembalikan nilai absolut yaitumath.sqrt(((a)**2)+((b)**2)

math.fabs(): Ini hanya bekerja pada nilai integer atau float. Selalu mengembalikan nilai float absolut apa pun tipe argumennya (kecuali untuk bilangan kompleks).

Rahul Talole
sumber