2024-09-27 17:37:53 发布
网友
使用math.pow或**运算符哪个更有效?我应该什么时候用一个代替另一个?
到目前为止,我知道x**y可以返回int或float,如果使用十进制 函数pow将返回一个浮点数
x**y
int
float
pow
import math print math.pow(10, 2) print 10. ** 2
使用power运算符**将更快,因为它没有函数调用的开销。如果反汇编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这样的常量表达式实际上是在编译时计算的。
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的速度大约是后者的两倍,但它们仍然足够快,不需要太多关注。除非你真的能将指数化识别为一个瓶颈,否则如果清晰度降低,就没有理由选择一种方法而不是另一种方法。这尤其适用,因为^{}提供了一个集成的模操作。
math.pow
阿尔夫在上面的评论中问了一个好问题:
timeit shows that math.pow is slower than ** in all cases. What is math.pow() good for anyway? Has anybody an idea where it can be of any advantage then?
timeit
math.pow()
与内置的pow和幂运算符**的最大区别在于它始终使用浮点语义。因此,如果出于某种原因,您想确保返回的结果是float,那么math.pow将确保此属性。
举个例子:我们有两个数字,i和j,不知道它们是浮点数还是整数。但是我们想要一个i^j的浮点结果。我们有什么选择?
j
i^j
i ** j
那么,让我们来测试一下:
>>> 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()。
float()
此外,值得注意的是,**和pow的行为可以通过为自定义类型实现特殊的__pow__(和__rpow__)方法来重写。因此,如果您不想这样做(无论出于什么原因),那么使用math.pow就不会这样做。
__pow__
__rpow__
嗯,他们是为不同的任务,真的。
如果需要整数运算,请使用pow(相当于带两个参数的x ** y)。
x ** y
如果其中一个参数是float,并且需要float输出,则使用math.pow。
有关pow和math.pow之间的区别的讨论,请参见本question。
仅对于协议:如果前两个参数是整数类型,则**运算符调用built-in ^{} 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版本使用的精度有限,这会导致错误。
0.0
为了公平起见,我们必须说,math.pow可以更快:
import timeit print timeit.timeit("math.pow(2, 100)",setup='import math') print timeit.timeit("pow(2, 100)")
以下是我的输出:
0.240936803195 1.4775809183
一些在线示例
使用power运算符
**
将更快,因为它没有函数调用的开销。如果反汇编Python代码,可以看到这一点:注意,我在这里使用变量
i
作为指数,因为像7. ** 5
这样的常量表达式实际上是在编译时计算的。现在,在实践中,这种差异并没有那么重要,正如你在计时时所看到的:
所以,虽然} 提供了一个集成的模操作。
pow
和math.pow
的速度大约是后者的两倍,但它们仍然足够快,不需要太多关注。除非你真的能将指数化识别为一个瓶颈,否则如果清晰度降低,就没有理由选择一种方法而不是另一种方法。这尤其适用,因为^{阿尔夫在上面的评论中问了一个好问题:
与内置的
pow
和幂运算符**
的最大区别在于它始终使用浮点语义。因此,如果出于某种原因,您想确保返回的结果是float,那么math.pow
将确保此属性。举个例子:我们有两个数字,
i
和j
,不知道它们是浮点数还是整数。但是我们想要一个i^j
的浮点结果。我们有什么选择?i ** j
。i ** j
并将结果转换为浮点(当i
或j
是浮点时,会自动使用浮点指数,因此结果是相同的)。math.pow
。那么,让我们来测试一下:
如您所见,
math.pow
实际上更快!如果你仔细想想,函数调用的开销现在也没有了,因为在所有其他选择中,我们都必须调用float()
。此外,值得注意的是,
**
和pow
的行为可以通过为自定义类型实现特殊的__pow__
(和__rpow__
)方法来重写。因此,如果您不想这样做(无论出于什么原因),那么使用math.pow
就不会这样做。嗯,他们是为不同的任务,真的。
如果需要整数运算,请使用
pow
(相当于带两个参数的x ** y
)。如果其中一个参数是float,并且需要float输出,则使用
math.pow
。有关
pow
和math.pow
之间的区别的讨论,请参见本question。仅对于协议:如果前两个参数是整数类型,则} function ,后者接受可选的第三个参数(模)。
**
运算符调用built-in ^{所以,如果你想计算来自异能的余数,使用内置函数。
math.pow
可能会给出错误的结果:当我运行这个程序时,我得到了
0.0
在第一个例子中,这显然不是真的,因为13是奇数(因此所有的积分幂)。math.pow
版本使用的精度有限,这会导致错误。为了公平起见,我们必须说,
math.pow
可以更快:以下是我的输出:
一些在线示例
math.pow
的余数错误)pow
会降低性能)pow
性能稍低)相关问题 更多 >
编程相关推荐