您正在運行到問題,因爲即使你的tie
功能的最後的結果應該是數學在0
和1
之間,中間值循環中的值變得非常大:對於total = 4962
,中途迭代的值爲prob
約爲1.5e308
,這是差不多但不是相當大到足以溢出Python float
。對於total = 4964
,價值中途真的確實溢出float
,由於inf
次有限東西仍然是inf
,在inf
從溢流傳播到最終值的所有道路。
如果您準備接受(相當小)的浮點錯誤數量,則不需要使用循環計算此數量:您可以使用math
模塊中的lgamma
函數來計算日誌的相關因子。 (您也可以直接使用gamma
函數,但這可能也會導致溢出問題。)
以下是基於此功能的一個版本。
from math import lgamma, log, exp
def tie(total):
count = total/2
return exp(lgamma(2*count + 1) - 2*lgamma(count + 1) - count*log(4))
或者,你可以使用純整數運算(這不會造成溢出)計算2N-選擇-N項,只在最後時刻產生浮(由4**count
分割時)。這樣做效率會比上面的要低,但會給你(從某種意義上來說)完美的準確性,因爲它會給出最接近的可表示的浮點數。下面是該版本是這樣的:
from __future__ import division
def tie(total):
count = total // 2
prod = 1
for i in xrange(1, count+1):
prod = prod * (count + i) // i
return prod/4**count
注:prod * (count + i) // i
地板師看起來可能不對,但它的實際工作:初等數論的一點點表明,在計算這一點上,prod * (count + i)
必須除盡由i
,所以它是安全的做一個整數除法。最後,爲了好玩,下面是第三種計算概率的方法,它與您的原始代碼在精神上相似,但是避免了溢出:值prob
開始於1.0
並穩步下降到最終值。
def tie(total):
count = total // 2
prob = 1.0
for i in xrange(1, count+1):
prob *= (i-0.5)/i
return prob
除了是從溢出問題免疫,這種解決方案會更高效,基於整數的解決方案,而不是基於lgamma
一個更準確。
將以下行添加到循環中:「print(」({} + {})/ {}/4「.format(prob,count,i,i))」您將看到發生了什麼 – MaxU
我在我的答案中添加了第三個解決方案,可能比基於整數的解決方案或基於lgamma的解決方案更適合您。 –