python x.** y与math.pow(x,y)的指数 [英] Exponentials in python x.**y vs math.pow(x, y)

查看:267
本文介绍了python x.** y与math.pow(x,y)的指数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用math.pow或**运算符哪个更有效?我什么时候应该在另一个上使用?

Which one is more efficient using math.pow or the ** operator? When should I use one over the other?

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

So far I know that x**y can return an int or a float if you use a decimal the function pow will return a float

import math

print math.pow(10, 2)

print 10. ** 2

推荐答案

使用超级运算符**会更快,因为它不会产生函数调用的开销.如果您反汇编Python代码,则可以看到以下内容:

Using the power operator ** will be faster as it won’t have the overhead of a function call. You can see this if you disassemble the Python code:

>>> 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这样的常量表达式实际上是在编译时求值的.

Note that I’m using a variable i as the exponent here because constant expressions like 7. ** 5 are actually evaluated at compile time.

现在,实际上,这种差异并不重要,正如您在计时时可以看到的那样:

Now, in practice, this difference does not matter that much, as you can see when timing it:

>>> 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 例如提供了集成的模运算.

So, while pow and math.pow are about twice as slow, they are still fast enough to not care much. Unless you can actually identify the exponentiation as a bottleneck, there won’t be a reason to choose one method over the other if clarity decreases. This especially applies since pow offers an integrated modulo operation for example.

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

Alfe asked a good question in the comments above:

timeit显示在所有情况下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?

math.pow与内置pow和幂运算符**的最大区别在于,它始终使用浮点语义.因此,如果由于某种原因要确保返回结果为浮点数,则math.pow将确保该属性.

The big difference of math.pow to both the builtin pow and the power operator ** is that it always uses float semantics. So if you, for some reason, want to make sure you get a float as a result back, then math.pow will ensure this property.

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

Let’s think of an example: We have two numbers, i and j, and have no idea if they are floats or integers. But we want to have a float result of i^j. So what options do we have?

  • 我们可以将至少一个参数转换为浮点数,然后执行i ** j.
  • 我们可以执行i ** j并将结果转换为浮点数(当ij为浮点数时,将自动使用浮点指数,因此结果相同).
  • 我们可以使用math.pow.
  • We can convert at least one of the arguments to a float and then do i ** j.
  • We can do i ** j and convert the result to a float (float exponentation is automatically used when either i or j are floats, so the result is the same).
  • We can use math.pow.

所以,我们对此进行测试:

So, let’s test this:

>>> 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().

As you can see, math.pow is actually faster! And if you think about it, the overhead from the function call is also gone now, because in all the other alternatives we have to call float().

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

In addition, it might be worth to note that the behavior of ** and pow can be overridden by implementing the special __pow__ (and __rpow__) method for custom types. So if you don’t want that (for whatever reason), using math.pow won’t do that.

这篇关于python x.** y与math.pow(x,y)的指数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆