簡體   English   中英

如何通過-0.0和0.0得到Python除法分別得到-Inf和Inf?

[英]How to get Python division by -0.0 and 0.0 to result in -Inf and Inf, respectively?

我有一種情況,即除以0.0或-0.0是合理的,我希望分別看到+ Inf和-Inf作為結果。 似乎Python喜歡拋出一個

ZeroDivisionError: float division by zero

在任一情況下。 顯然,我認為我可以用0.0的測試簡單地包裝它。 但是,我找不到區分+0.0和-0.0的方法。 (僅供參考,您可以通過鍵入或通過常見計算(例如-1.0 * 0.0)輕松獲得-0.0。

IEEE非常好地處理了這一切,但Python似乎很難隱藏經過深思熟慮的IEEE行為。 事實上,0.0 == -0.0實際上是一個IEEE功能,因此Python的行為嚴重破壞了事情。 它在C,Java,Tcl甚至JavaScript中運行良好。

建議?

from math import copysign

def divide(numerator, denominator):
    if denominator == 0.0:
        return copysign(float('inf'), denominator)
    return numerator / denominator

>>> divide(1, -0.0)
-inf
>>> divide(1, 0)
inf

我完全同意@Mark Ransom,除了我會try使用try

def f(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return copysign(float('inf'), denominator)

我建議這樣做的原因是,如果您多次執行此功能,則在嘗試除法之前,如果值為零,則不必浪費時間進行每次迭代檢查。

編輯

我將try的速度與if函數進行了比較:

def g(a, b):
    if b == 0:
        return copysign(float('inf'), b)
    else:
        return a / b

這是測試:

s = time.time()
[f(10, x) for x in xrange(-1000000, 1000000, 1)]
print 'try:', time.time()-s
s = time.time()
[g(10, x) for x in xrange(-1000000, 1000000, 1)]
print 'if:', time.time()-s

結果如下:

try: 0.573683023453
if: 0.610251903534

這表明try方法更快,至少在我的機器上。

gmpy2庫提供任意精度浮點類型,還允許您控制IEEE-754異常行為。

>>> import gmpy2
>>> from gmpy2 import mpfr
>>> mpfr(1)/mpfr(0)
mpfr('inf')
>>> mpfr(1)/mpfr(-0)
mpfr('inf')
>>> mpfr(1)/mpfr("-0")
mpfr('-inf')
>>> gmpy2.get_context().trap_divzero=True
>>> mpfr(1)/mpfr(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
gmpy2.DivisionByZeroError: 'mpfr' division by zero in division

免責聲明:我維持gmpy2。

這是一個正確處理所有邊緣情況的解決方案,至少據我所知:

def divide(a: float, b: float) -> float:
    try:
        return a/b
    except:
        return a*math.copysign(math.inf, b)

assert divide( 1,  1) ==  1
assert divide( 1, -1) == -1
assert divide(-1,  1) == -1
assert divide(-1, -1) ==  1
assert divide( 1,  0.0) >  1e300
assert divide( 1, -0.0) < -1e300
assert divide(-1,  0.0) < -1e300
assert divide(-1, -0.0) >  1e300
assert math.isnan(divide( 0.0,  0.0))
assert math.isnan(divide( 0.0, -0.0))
assert math.isnan(divide(-0.0,  0.0))
assert math.isnan(divide(-0.0, -0.0))

b為零的情況下,它基本上將除法a/b分成a * (1/b)並通過copysign()實現1/b 當參數為0*inf ,乘法不會拋出,而是正確地產生NAN。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM