python x中的指数。** y vs math.pow(x,y)

时间:2014-01-07 10:52:57

标签: python math built-in pow

使用math.pow或**运算符哪一个更有效?我何时应该使用另一个?

到目前为止,我知道如果您使用小数,x**y可以返回intfloat 函数pow将返回一个浮点数

import math

print math.pow(10, 2)

print 10. ** 2

5 个答案:

答案 0 :(得分:76)

使用幂运算符**会更快,因为它不会有函数调用的开销。如果你反汇编Python代码,你可以看到这个:

>>> dis.dis('7. ** i')
  1           0 LOAD_CONST               0 (7.0) 
              3 LOAD_NAME                0 (i) 
              6 BINARY_POWER         
              7 RETURN_VALUE         
>>> dis.dis('pow(7., i)')
  1           0 LOAD_NAME                0 (pow) 
              3 LOAD_CONST               0 (7.0) 
              6 LOAD_NAME                1 (i) 
              9 CALL_FUNCTION            2 (2 positional, 0 keyword pair) 
             12 RETURN_VALUE         
>>> dis.dis('math.pow(7, i)')
  1           0 LOAD_NAME                0 (math) 
              3 LOAD_ATTR                1 (pow) 
              6 LOAD_CONST               0 (7) 
              9 LOAD_NAME                2 (i) 
             12 CALL_FUNCTION            2 (2 positional, 0 keyword pair) 
             15 RETURN_VALUE         

请注意,我在这里使用变量i作为指数,因为7. ** 5之类的常量表达式实际上是在编译时计算的。

现在,在实践中,这种差异并不重要,正如您在计时时所看到的那样:

>>> from timeit import timeit
>>> timeit('7. ** i', setup='i = 5')
0.2894785532627111
>>> timeit('pow(7., i)', setup='i = 5')
0.41218495570683444
>>> timeit('math.pow(7, i)', setup='import math; i = 5')
0.5655053168791255

因此,虽然powmath.pow的速度大约是其两倍,但它们仍然足够快,不会太在意。除非您能够将指数确定为瓶颈,否则如果清晰度降低,则没有理由选择一种方法而不是另一种方法。这尤其适用,因为pow提供了一个集成的模运算,例如。


Alfe在上面的评论中提出了一个很好的问题:

  

timeit表明math.pow在所有情况下都比**慢。无论如何,math.pow()有什么好处?有人知道它可以带来什么优势吗?

math.pow与内置pow和幂运算符**的巨大差异在于始终使用float语义。因此,如果您出于某种原因想要确保返回一个浮点数,那么math.pow将确保此属性。

让我们想一个例子:我们有两个数字ij,并且不知道它们是浮点数还是整数。但是我们希望浮点结果为i^j。那么我们有什么选择呢?

  • 我们可以将至少一个参数转换为float,然后执行i ** j
  • 我们可以执行i ** j并将结果转换为float(当ij为浮点数时,会自动使用float exponent,因此结果相同)。
  • 我们可以使用math.pow

所以,让我们测试一下:

>>> timeit('float(i) ** j', setup='i, j = 7, 5')
0.7610865891750791
>>> timeit('i ** float(j)', setup='i, j = 7, 5')
0.7930400942188385
>>> timeit('float(i ** j)', setup='i, j = 7, 5')
0.8946636625872202
>>> timeit('math.pow(i, j)', setup='import math; i, j = 7, 5')
0.5699394063529439

如您所见,math.pow实际上更快!如果你考虑一下,函数调用的开销现在也消失了,因为在所有其他选择中我们必须调用float()


此外,值得注意的是,**pow的行为可以通过为自定义实施特殊的__pow__(和__rpow__)方法来覆盖类型。因此,如果您不希望(无论出于何种原因),使用math.pow将不会这样做。

答案 1 :(得分:4)

仅针对协议:如果前两个参数是整数类型,**运算符调用built-in pow function,它接受​​可选的第三个参数(模数)。

因此,如果您打算从权力计算余数,请使用内置函数。 math.pow可能会给您错误的结果:

import math

base = 13
exp = 100
mod = 2
print math.pow(base, exp) % mod
print pow(base, exp, mod)

当我跑步时,我在第一种情况下得到0.0,显然不可能是真的,因为13是奇数(因此它是所有的整数幂)。 math.pow版本使用的精度有限,会导致错误。

为了公平起见,我们必须说,math.pow可以更快:

import timeit
print timeit.timeit("math.pow(2, 100)",setup='import math')
print timeit.timeit("pow(2, 100)")

以下是我输出的内容:

0.240936803195
1.4775809183

一些在线示例

答案 2 :(得分:3)

嗯,他们真的是为了完成不同的任务。

当您想要整数运算时,请使用pow(相当于x ** y有两个参数)。

如果任一参数为float,并且您想要浮点输出,请使用math.pow

有关powmath.pow之间差异的讨论,请参阅此question

答案 3 :(得分:2)

**确实比math.pow()更快,但如果你想要一个简单的二次函数,就像在你的例子中一样,使用产品会更快。

10.*10.

会更快

10.**2

差异不大,一个操作(使用timeit)并不明显,但是有大量操作可能很重要。

答案 4 :(得分:1)

pow()函数将允许您添加第三个参数作为模数。

例如:最近我在做

时遇到内存错误
  

2 ** 23375247598357347582%23375247598357347583

相反,我做了:

  

execute

这将返回毫秒数,而不是简单的指数所花费的大量时间和内存。因此,当处理大数和并行模数时,pow()效率更高,但是当处理小数而无模数时,**效率更高。