![](/img/trans.png)
[英]Python: When would 0.0/0.0 =NaN or inf , when would it gives exception?
[英]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.