python x.**y 与 math.pow(x, y) 中的指数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20969773/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Exponentials in python x.**y vs math.pow(x, y)
提问by user3084006
Which one is more efficient using math.pow or the ** operator? When should I use one over the other?
使用 math.pow 或 ** 运算符哪个更有效?我什么时候应该使用一个?
So far I know that x**ycan return an intor a floatif you use a decimal
the function powwill return a float
到目前为止,我知道x**y可以返回 anint或 afloat如果您使用小数,该函数pow将返回一个浮点数
import math
print math.pow(10, 2)
print 10. ** 2
采纳答案by poke
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:
使用幂运算符**会更快,因为它没有函数调用的开销。如果反汇编 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
Note that I'm using a variable ias the exponent here because constant expressions like 7. ** 5are actually evaluated at compile time.
请注意,我在这里使用变量i作为指数,因为像这样的常量表达式7. ** 5实际上是在编译时计算的。
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
So, while powand math.poware 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 powoffers an integrated modulo operation for example.
因此,虽然pow和math.pow的速度大约是其两倍,但它们仍然足够快,不会太在意。除非您实际上可以将求幂确定为瓶颈,否则如果清晰度降低,就没有理由选择一种方法而不是另一种方法。这尤其适用,因为pow例如提供了集成的模运算。
Alfe asked a good question in the comments above:
Alfe 在上面的评论中提出了一个很好的问题:
timeitshows thatmath.powis slower than**in all cases. What ismath.pow()good for anyway? Has anybody an idea where it can be of any advantage then?
timeit表明这math.pow比**所有情况下都慢。有什么math.pow()好处呢?有没有人知道它可以有什么优势呢?
The big difference of math.powto both the builtin powand the power operator **is that it alwaysuses float semantics. So if you, for some reason, want to make sure you get a float as a result back, then math.powwill ensure this property.
math.pow内置pow运算符和幂运算符的最大区别**在于它始终使用浮点语义。因此,如果您出于某种原因想要确保返回浮点数,那么math.pow将确保此属性。
Let's think of an example: We have two numbers, iand 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. 那么我们有哪些选择呢?
- We can convert at least one of the arguments to a float and then do
i ** j. - We can do
i ** jand convert the result to a float (float exponentation is automatically used when eitheriorjare floats, so the result is the same). - We can use
math.pow.
- 我们可以将至少一个参数转换为浮点数,然后执行
i ** j. - 我们可以
i ** j将结果转换为浮点数(当i或j是浮点数时自动使用浮点指数,因此结果相同)。 - 我们可以使用
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
As you can see, math.powis 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().
如您所见,math.pow实际上更快!如果您考虑一下,函数调用的开销现在也没有了,因为在所有其他替代方案中,我们必须调用float().
In addition, it might be worth to note that the behavior of **and powcan 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.powwon't do that.
此外,可能值得注意的是,**和的行为pow可以通过为自定义类型实现特殊__pow__(和__rpow__)方法来覆盖。因此,如果您不想要(无论出于何种原因),则使用math.pow不会这样做。
回答by wim
Well, they are for different tasks, really.
好吧,它们确实用于不同的任务。
Use pow(equivalent to x ** ywith two arguments) when you want integer arithmetic.
当您需要整数算术时使用pow(相当于x ** y使用两个参数)。
And use math.powif either argument is float, and you want float output.
并使用math.pow你想浮动输出,如果任一参数为float和。
For a discussion on the differences between powand math.pow, see this question.
有关pow和之间差异的讨论math.pow,请参阅此问题。
回答by Wolf
Just for the protocol: The **operator calls the built-in powfunctionwhich accepts an optional third argument (modulus) if the first two arguments are integer types.
仅针对协议:如果前两个参数是整数类型,则**运算符调用内置pow函数,该函数接受可选的第三个参数(模数)。
So, if you intend to calculate remainders from powers, use the built-in function. The math.powmay give you false results:
因此,如果您打算根据幂计算余数,请使用内置函数。在math.pow可能给你错误的结果:
import math
base = 13
exp = 100
mod = 2
print math.pow(base, exp) % mod
print pow(base, exp, mod)
When I ran this, I got 0.0in the first case which obviously cannot be true, because 13 is odd (and therefore all of it's integral powers). The math.powversion uses limited accuracy which causes an error.
当我运行这个时,我遇到0.0了第一种情况,这显然不可能是真的,因为 13 是奇数(因此它是整数幂)。该math.pow版本使用有限的准确性,这会导致错误。
For sake of fairness, we must say, math.powcan be much faster:
为了公平起见,我们必须说,math.pow可以更快:
import timeit
print timeit.timeit("math.pow(2, 100)",setup='import math')
print timeit.timeit("pow(2, 100)")
Here is what I'm getting as output:
这是我得到的输出:
0.240936803195
1.4775809183
Some online examples
一些网上例子
- http://ideone.com/qaDWRd(wrong remainder with
math.pow) - http://ideone.com/g7J9Un(lower performance with
powon int values) - http://ideone.com/KnEtXj(slightly lower performance with
powon float values)
- http://ideone.com/qaDWRd(错误的余数
math.pow) - http://ideone.com/g7J9Un(使用
powint 值时性能较低) - http://ideone.com/KnEtXj(使用
pow浮点值时性能略低)
回答by KDhoore
**is indeed faster then math.pow(), but if you want a simple quadratic function like in your example it is even faster to use a product.
**确实更快math.pow(),但如果你想要一个简单的二次函数,就像你的例子一样,使用产品会更快。
10.*10.
will be faster then
然后会更快
10.**2
The difference is not big and not noticable with one operation (using timeit), but with a large number of operations it can be significant.
对于一次操作(使用timeit),差异不大且不明显,但对于大量操作,差异可能很大。
回答by bravoalpha90
The pow() function will allow you to add a third argument as a modulus.
pow() 函数将允许您添加第三个参数作为模数。
For example: I was recently faced with a memory error when doing
例如:我最近在做的时候遇到了内存错误
2**23375247598357347582 % 23375247598357347583
2**23375247598357347582 % 23375247598357347583
Instead I did:
相反,我做了:
pow(2, 23375247598357347582, 23375247598357347583)
pow(2, 23375247598357347582, 23375247598357347583)
This returns in mere milliseconds instead of the massive amount of time and memory that the plain exponent takes. So, when dealing with large numbers and parallel modulus, pow() is more efficient, however when dealing with smaller numbers without modulus, ** is more efficient.
这仅在几毫秒内返回,而不是普通指数占用的大量时间和内存。因此,在处理大数和并行模数时,pow() 更有效,但是在处理没有模数的较小数时,** 更有效。

