Python - abs vs fabs


107

Tôi nhận thấy rằng trong python có hai phương pháp tìm kiếm tương tự để tìm giá trị tuyệt đối của một số:

Đầu tiên

abs(-5)

Thứ hai

import math
math.fabs(-5)

Các phương pháp này khác nhau như thế nào?

Câu trả lời:


127

math.fabs()chuyển đổi đối số của nó thành float nếu nó có thể (nếu nó không thể, nó ném một ngoại lệ). Sau đó, nó nhận giá trị tuyệt đối và trả về kết quả dưới dạng một số thực.

Ngoài float, abs()cũng hoạt động với số nguyên và số phức. Kiểu trả về của nó phụ thuộc vào kiểu đối số của nó.

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
abshoạt động với nhiều thứ hơn là chỉ số nguyên và số float, và kiểu kết quả không phải lúc nào cũng giống với đối số, ví dụ abs(3+4j).
AGF

1
thêm nhận xét về fabsviệc mất nhiều thời gian hơn do tính chất luôn trôi nổi của nó và bạn đã có câu trả lời đúng!
Patrick Perini

@agf: Cảm ơn vì đã nhắc tôi về số phức. Ngoài sự quan tâm, những lớp thứ nào khác có thể __builtin__.abs()được áp dụng thành công?
NPE

5
@aix Bất kỳ người dùng định nghĩa lớp định nghĩa các __abs__phương pháp kỳ diệu
AGF

9

Chỉnh sửa: như @aix đã đề xuất, một cách tốt hơn (công bằng hơn) để so sánh sự khác biệt về tốc độ:

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

Vì vậy, nó có vẻ như abs()chỉ có một chút lợi thế về tốc độ đối fabs()với số nguyên. Đối với phao, abs()fabs()chứng minh tốc độ tương tự.


Ngoài những gì @aix đã nói, một điều nữa cần xem xét là sự khác biệt về tốc độ:

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

Vì vậy, abs()là nhanh hơn math.fabs().


3
Bạn không so sánh táo với táo ở đó. Sử dụng from math import fabscho chắc chắn, và cố gắng -5.0cho cả hai.
AGF

Ngoài ra kết quả thời gian không đáng tin cậy? Đầu tiên bạn có cơ bụng (-5) ở 102ns, sau đó hiển thị là 88.3ns. Không bao giờ đưa ra kết luận từ một lần chạy bất kỳ điểm chuẩn nào, ngay cả khi nó cố gắng tránh các vấn đề như thời gian.
Peter Hansen

1
Hai điểm nữa: điều này vẫn so sánh táo và cam, vì abs được tìm kiếm trong nội trang, trong khi fabs ở không gian tên mô-đun. Thực hiện "xabs = abs" rồi xabs (num) để loại bỏ hiệu ứng đó. Ngoài ra, với Python 3.2, mọi thứ thay đổi khá nhiều và dường như abs () nhanh hơn một chút (> 2x), ít nhất là trên float.
Peter Hansen

1
@PeterHansen Bạn nói đúng, đó là từ hai lần chạy dưới các tải hệ thống khác nhau. Mặc dù khi so sánh trong cùng một bộ thử nghiệm, sự khác biệt tương đối vẫn có giá trị. Ngoài ra, cảm ơn bạn đã chỉ ra sự khác biệt về không gian tên - tôi đã không xem xét điều đó. Tôi đã không thử nó trên 3.2, nhưng điều đó tốt để biết! Tôi sẽ cập nhật câu trả lời của tôi với các đề xuất của bạn sau :) Cảm ơn một lần nữa!
KZ

3

math.fabs()luôn trả về float, while abs()có thể trả về số nguyên.


6
abscó thể trả về bất kỳ kiểu nào, tùy thuộc vào __abs__phương thức đặc biệt của kiểu mà nó được gọi.
AGF

0

abs(): Trả về giá trị tuyệt đối cho mỗi đối số, tức là nếu đối số là int thì nó trả về int, nếu đối số là float thì trả về float. Ngoài ra, nó hoạt động trên biến phức cũng tức là abs(a+bj)cũng hoạt động và trả về giá trị tuyệt đối tức làmath.sqrt(((a)**2)+((b)**2)

math.fabs(): Nó chỉ hoạt động trên các giá trị số nguyên hoặc số thực. Luôn trả về giá trị float tuyệt đối bất kể kiểu đối số là gì (ngoại trừ số phức).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.