Python - abs กับ fabs


107

ฉันสังเกตว่าใน python มีวิธีการค้นหาที่คล้ายกันสองวิธีในการหาค่าสัมบูรณ์ของตัวเลข:

อันดับแรก

abs(-5)

ประการที่สอง

import math
math.fabs(-5)

วิธีการเหล่านี้แตกต่างกันอย่างไร?

คำตอบ:


127

math.fabs()แปลงอาร์กิวเมนต์เป็น float ถ้าทำได้ (ถ้าทำไม่ได้มันจะแสดงข้อยกเว้น) จากนั้นรับค่าสัมบูรณ์และส่งคืนผลลัพธ์เป็นทศนิยม

นอกจากลอยแล้วabs()ยังใช้งานได้กับจำนวนเต็มและจำนวนเชิงซ้อน ประเภทผลตอบแทนขึ้นอยู่กับประเภทของอาร์กิวเมนต์

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
absทำงานร่วมกับไกลกว่าเพียงจำนวนเต็มและลอยและประเภทของผลที่ได้คือไม่abs(3+4j)เสมอกันเป็นอาร์กิวเมนต์เช่น
agf

1
เพิ่มความคิดเห็นเกี่ยวกับfabsการใช้เวลานานขึ้นเนื่องจากลักษณะของการลอยตัวตลอดเวลาและคุณมีคำตอบที่ถูกต้อง!
Patrick Perini

@agf: ขอบคุณที่เตือนฉันเกี่ยวกับจำนวนเชิงซ้อน ไม่น่าสนใจสิ่งอื่นใดที่สามารถ__builtin__.abs()นำไปใช้กับได้สำเร็จ?
NPE

5
@aix ผู้ใช้กำหนดคลาสใด ๆ ที่กำหนด__abs__เมธอดมายากล
agf

9

แก้ไข: ตามที่ @aix แนะนำวิธีที่ดีกว่า (ยุติธรรมกว่า) ในการเปรียบเทียบความแตกต่างของความเร็ว:

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

ดูเหมือนว่าabs()จะมีข้อได้เปรียบด้านความเร็วเล็กน้อยfabs()สำหรับจำนวนเต็ม สำหรับการลอยตัวabs()และfabs()แสดงให้เห็นถึงความเร็วที่ใกล้เคียงกัน


นอกเหนือจากสิ่งที่ @aix กล่าวแล้วอีกสิ่งหนึ่งที่ต้องพิจารณาคือความแตกต่างของความเร็ว:

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

ดังนั้นจะเร็วกว่าabs()math.fabs()


3
คุณไม่ได้เปรียบเทียบแอปเปิ้ลกับแอปเปิ้ลที่นั่น ใช้อย่างfrom math import fabsแน่นอนและลอง-5.0ทั้งสองอย่าง
agf

ผลการจับเวลาที่ไม่น่าเชื่อถือด้วย? ครั้งแรกคุณมี abs (-5) ที่ 102ns จากนั้นจึงแสดงเป็น 88.3ns อย่าหาข้อสรุปจากการใช้เกณฑ์มาตรฐานใด ๆ แม้ว่าภายในจะพยายามหลีกเลี่ยงปัญหาตามเวลาก็ตาม
Peter Hansen

1
อีกสองประเด็น: สิ่งนี้ยังคงเปรียบเทียบแอปเปิ้ลและส้มเนื่องจาก ABS ถูกค้นหาในบิวด์อินในขณะที่ fabs อยู่ที่เนมสเปซโมดูล ทำ "xabs = abs" ตามด้วย xabs (num) เพื่อลบเอฟเฟกต์นั้น นอกจากนี้ด้วย Python 3.2 สิ่งต่าง ๆ ก็เปลี่ยนไปเล็กน้อยและเห็นได้ชัดว่า abs () ค่อนข้างเร็วกว่าเล็กน้อย (> 2x) อย่างน้อยก็ในการลอยตัว
Peter Hansen

1
@PeterHansen คุณพูดถูกสิ่งเหล่านี้มาจากสองการทำงานภายใต้การโหลดระบบที่แตกต่างกัน แม้ว่าเมื่อเปรียบเทียบภายในชุดการทดสอบเดียวกันความแตกต่างสัมพัทธ์ยังคงใช้ได้ นอกจากนี้ขอขอบคุณที่ชี้ให้เห็นความแตกต่างของเนมสเปซ - ฉันไม่ได้พิจารณาอย่างนั้น ฉันยังไม่ได้ลองใช้กับ 3.2 แต่ก็น่ารู้! ฉันจะอัปเดตคำตอบพร้อมคำแนะนำของคุณในภายหลัง :) ขอบคุณอีกครั้ง!
KZ

3

math.fabs()คืนค่าลอยเสมอในขณะที่abs()อาจส่งคืนจำนวนเต็ม


6
absอาจส่งคืนประเภทใดก็ได้ขึ้นอยู่กับ__abs__วิธีการพิเศษของประเภทที่เรียกใช้
agf

0

abs(): ส่งคืนค่าสัมบูรณ์ตามอาร์กิวเมนต์เช่นถ้าอาร์กิวเมนต์เป็น int แล้วมันจะส่งกลับ int ถ้าอาร์กิวเมนต์เป็น float มันจะส่งกลับ float นอกจากนี้ยังทำงานกับตัวแปรที่ซับซ้อนเช่นabs(a+bj)ยังทำงานและส่งกลับค่าสัมบูรณ์เช่นmath.sqrt(((a)**2)+((b)**2)

math.fabs(): ใช้ได้เฉพาะกับค่าจำนวนเต็มหรือค่าลอย ส่งคืนค่าสัมบูรณ์ลอยตัวเสมอไม่ว่าอาร์กิวเมนต์จะเป็นประเภทใด (ยกเว้นจำนวนเชิงซ้อน)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.