2012-08-30 247 views
1

我正在檢出doctest並將該因子示例複製到了我的編輯器中。由於使用遞歸感覺更多的函數式編程,我覺得像這樣改變例子;爲什麼遞歸更改結果?

def factorial(n): 
    # ... omitted 
    if n+1 == n: # catch a value like 1e300 
     raise OverflowError("n too large") 

    if n == 0: 
     return 1 
    else: 
     return factorial(n - 1) * n 

在此更改後,其中一個測試失敗;

Failed example: 
    factorial(30.0) 
Expected: 
    265252859812191058636308480000000L 
Got: 
    2.6525285981219103e+32 

這種差異的原因是什麼?

回答

5

嘗試使用factorial(30)而不是factorial(30.0)運行。浮點加法不像整數加法那樣精確,所以你會在一段時間後看到錯誤。

考慮:

>>> 1e20 + 1 == 1e20 #True 

這是因爲你沒有足夠的精度(位)來存儲這些數字的唯一。 (一個典型的python float有64位,這意味着你有2 ** 64個獨特的組合 - 大約在​​選項的某處。但是,python float的最大大小爲sys.float_info.max,大多數系統的大小約爲1.8e308,所以無法存儲每個積分值都是唯一的 - 尤其是當你認爲浮點數可以容納更多的整數值時)

個人而言,我只是將n的值轉換爲factorial函數中的整數,因爲factorial僅定義爲整數 - 可能檢查,以確保abs(int(n) - n) < 1e-5或某事的影響。

+0

爲什麼不拋出OverflowError?啊!我明白了,它在** n **上拋出一個錯誤。 –

+0

Python具有任意精度的長整數。 – mgilson

1

你輸入的數字是一個浮點數。既然你沒有把它轉換成int,你會在輸出中得到一個浮點數。