2012-02-07 59 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