use*_*006 40 python math built-in pow
哪一个使用math.pow或**运算符更有效?我什么时候应该使用另一个?
到目前为止我知道x**y可以返回一个int或者float如果你使用十进制函数pow将返回一个浮点数
import math
print math.pow(10, 2)
print 10. ** 2
Run Code Online (Sandbox Code Playgroud)
pok*_*oke 81
使用幂运算符**会更快,因为它不会有函数调用的开销.如果你反汇编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
Run Code Online (Sandbox Code Playgroud)
请注意,我在这里使用变量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
Run Code Online (Sandbox Code Playgroud)
因此,虽然速度pow和math.pow速度差不多两倍,但它们仍然足够快,不会太在意.除非您能够将指数确定为瓶颈,否则如果清晰度降低,则没有理由选择一种方法而不是另一种方法.这尤其适用,因为pow例如提供集成的模运算.
阿尔芬在上面的评论中提出了一个很好的问题:
timeit显示math.pow比**所有情况都慢.math.pow()无论如何有什么好处?有人知道它可以有什么优势吗?
math.pow内置函数pow和幂**函数的最大区别在于它总是使用浮点语义.因此,如果您出于某种原因想要确保返回一个浮点数,那么math.pow将确保此属性.
让我们想一个例子:我们有两个数字,i并且j不知道它们是浮点数还是整数.但我们希望得到一个浮动结果i^j.那么我们有什么选择呢?
i ** j.i ** j,结果转换为浮动(浮动求幂将自动使用时,无论是i或j有浮动,所以结果是一样的).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
Run Code Online (Sandbox Code Playgroud)
如你所见,math.pow实际上更快!如果你考虑一下,函数调用的开销现在也消失了,因为在所有其他选择中我们必须调用float().
此外,值得注意的是,通过为自定义类型实现特殊(和)方法可以覆盖**和的行为.因此,如果您不想要(无论出于何种原因),使用将不会那样做.pow__pow____rpow__math.pow
bra*_*a90 17
pow() 函数将允许您添加第三个参数作为模数。
例如:我最近在做的时候遇到了内存错误
2**23375247598357347582 % 23375247598357347583
相反,我做了:
pow(2, 23375247598357347582, 23375247598357347583)
这仅在几毫秒内返回,而不是普通指数占用的大量时间和内存。因此,在处理大数和并行模数时,pow() 更有效,但是在处理没有模数的较小数时,** 更有效。
仅针对协议:**运算符等效于内置pow函数的双参数版本,如果前两个参数是整数,则该pow 函数接受可选的第三个参数(模数)。
因此,如果您打算根据幂计算余数,请使用内置函数。该math.pow会给你合理的大小的参数错误的结果:
import math
base = 13
exp = 100
mod = 2
print math.pow(base, exp) % mod
print pow(base, exp, mod)
Run Code Online (Sandbox Code Playgroud)
当我运行这个时,我遇到0.0了第一种情况,这显然不可能是真的,因为 13 是奇数(因此它是整数幂)。该math.pow版本使用IEEE-754 双精度(52 位尾数,略小于 16 位小数)的有限精度,这会导致这里出现错误。
为了公平起见,我们必须说,math.pow 可以也更快:
import math
base = 13
exp = 100
mod = 2
print math.pow(base, exp) % mod
print pow(base, exp, mod)
Run Code Online (Sandbox Code Playgroud)
该math.pow函数在工程应用中具有(并且仍然具有)其优势,但对于数字理论应用,您应该使用内置pow函数。
一些网上例子
math.pow)powint 值时性能较低)pow浮点值时性能略低)更新(不可避免的修正):
我删除的时间比较math.pow(2,100)和pow(2,100)因为math.pow给出了一个错误的结果,而在例如,之间的比较pow(2,50),并math.pow(2,50)会一直公平(虽然不是一个现实使用的math-module功能)。我添加了一个更好的以及导致math.pow.
小智 5
**确实更快math.pow(),但如果你想要一个简单的二次函数,就像你的例子一样,使用产品会更快。
10.*10.
Run Code Online (Sandbox Code Playgroud)
然后会更快
10.**2
Run Code Online (Sandbox Code Playgroud)
对于一次操作(使用timeit),差异不大且不明显,但对于大量操作,差异可能很大。
| 归档时间: |
|
| 查看次数: |
40565 次 |
| 最近记录: |