使用math.pow或**运算符哪一个更有效?我何时应该使用另一个?
到目前为止,我知道如果您使用小数,x**y
可以返回int
或float
函数pow
将返回一个浮点数
import math
print math.pow(10, 2)
print 10. ** 2
答案 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
因此,虽然pow
和math.pow
的速度大约是其两倍,但它们仍然足够快,不会太在意。除非您能够将指数确定为瓶颈,否则如果清晰度降低,则没有理由选择一种方法而不是另一种方法。这尤其适用,因为pow
提供了一个集成的模运算,例如。
Alfe在上面的评论中提出了一个很好的问题:
timeit
表明math.pow
在所有情况下都比**
慢。无论如何,math.pow()
有什么好处?有人知道它可以带来什么优势吗?
math.pow
与内置pow
和幂运算符**
的巨大差异在于始终使用float语义。因此,如果您出于某种原因想要确保返回一个浮点数,那么math.pow
将确保此属性。
让我们想一个例子:我们有两个数字i
和j
,并且不知道它们是浮点数还是整数。但是我们希望浮点结果为i^j
。那么我们有什么选择呢?
i ** j
。i ** j
并将结果转换为float(当i
或j
为浮点数时,会自动使用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
一些在线示例
math.pow
)pow
性能较低)pow
的性能略低)答案 2 :(得分:3)
嗯,他们真的是为了完成不同的任务。
当您想要整数运算时,请使用pow
(相当于x ** y
有两个参数)。
如果任一参数为float,并且您想要浮点输出,请使用math.pow
。
有关pow
和math.pow
之间差异的讨论,请参阅此question。
答案 3 :(得分:2)
**
确实比math.pow()
更快,但如果你想要一个简单的二次函数,就像在你的例子中一样,使用产品会更快。
10.*10.
会更快
10.**2
差异不大,一个操作(使用timeit
)并不明显,但是有大量操作可能很重要。
答案 4 :(得分:1)
pow()函数将允许您添加第三个参数作为模数。
例如:最近我在做
时遇到内存错误2 ** 23375247598357347582%23375247598357347583
相反,我做了:
execute
这将返回毫秒数,而不是简单的指数所花费的大量时间和内存。因此,当处理大数和并行模数时,pow()效率更高,但是当处理小数而无模数时,**效率更高。