2012-02-07 56 views
1

我一直在試驗標準的Python數學模塊,並遇到了一些微妙的困難。例如,我注意到有關不定形以下行爲:Python數學模塊微妙

0**0 

>>> 1 

def inf(): 
    return 1e900 
    # Will return inf 

inf()**inf() 

>>> inf 

和其它種類的異常。我正在寫一個計算器,我希望它在數學上是準確的。我能做些什麼嗎?或者,有什麼辦法可以繞過這個?提前致謝。

+2

您需要知道浮點數是如何工作的:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – duffymo 2012-02-07 03:11:39

+1

從來不知道Python說0^0 == 1>。< – Corbin 2012-02-07 03:12:17

+0

究竟是什麼不喜歡這些結果? – sth 2012-02-07 03:15:33

回答

2

你的第一個例子沒有問題。 0**0通常被定義爲1.第二個例子是所有與雙精度有關的事情。 1E900超過(最有可能的64位)雙倍的最大正值。如果你想在這個範圍之外加倍,你必須看看圖書館。幸運的是Python有一個內置的:the decimal module

例如:

from decimal import Decimal 
d = Decimal('1E900') 
f = d + d 
print(f) 
>>> 2E900 
+0

謝謝!我不知道十進制模塊,應該派上用場。 – ThisIsNotAnId 2012-02-08 00:51:52

2

根據鎢(引用Knuth的),而0 ** 0是不確定的,它有時給定爲1,這是因爲保持該語句的 'x ** 0 = 1' 到在所有情況下都是如此,在某些情況下是有用的。更有趣的是,Python將NaN ** 0視爲1。

http://mathworld.wolfram.com/Power.html

在無窮**無窮大,你沒有真正處理無窮的數學概念在這裏(其中那將是不確定的)的情況下,而是一個數字太大了,而且已經溢出。因此,這句話所說的是,對於另一個龐大的數字來說,巨大的數字仍然是一個巨大的數字。

編輯:我不認爲有可能在Python中重載內置類型(例如float),以便直接重載float .__ pow __(x,y)運算符。你可能做的是定義你自己的float版本。

class myfloat(float): 
    def __pow__(x,y): 
     if(x==y==0): 
      return 'NaN' 
     else: 
      return float.__pow__(x,y) 

m = myfloat(0) 
m**0 

不確定這是不是你正在尋找的。

+0

謝謝MDT。有沒有辦法解決?例如,對於我的計算器,我能否以某種方式告訴解釋器是否遇到'0 ** 0'輸入(不一定是字符串),返回''Indeterminate form.''? – ThisIsNotAnId 2012-02-07 05:46:55

1

如果我們假設0**0 == 1,那麼返回NaN的0**0幾乎總是毫無用處,許多算法避免了特殊情況。所以雖然它可能不是數學上的完美 - 我們在這裏談論IEEE-754,但數學正確性實際上是我們問題中最少的[1]

但是如果你想改變它,那很簡單。下面將按預期在Python 3.2:

def my_pow(x, y): 
    if y == 0: return 'NaN' 
    return float.__pow__(float(x), y) 

pow = my_pow 

[1]下面的代碼在理論上可以執行如果與x86處理器(以及至少在C和共)分支:

float x = sqrt(y); 
if (x != sqrt(y)) printf("Surprise, surprise!\n"); 
+0

出於興趣,這是否意味着0 ** 0將返回'NaN'或者只是pow(0,0)? (0 ** 0在2.7中仍然返回1,但我沒有3.2來測試它) – MDT 2012-02-08 09:31:29

+0

@MDT完全忘記了python啓用了**操作符,可悲的是,這不適用於'**'在python3下:(我只是反彙編它,'**'使用'BINARY_POWER'操作碼,所以我們無法改變它,而無需更改c代碼並重新編譯解釋器 – Voo 2012-02-08 13:32:01