本问题已经有最佳答案,请猛点这里访问。
所以我一直在看到人们写代码,当他们希望看到给定值的平方形式时,他们会写出x * x而不是x ** 2。 这两个点之间是否存在很大的效率重叠,是不是仅使用了python中的给定函数,还是仅仅是一个风格上的点? 我宁愿使用**运算符,但是如果它会引起极大的失误,我是否应该执行该操作十亿次,我知道的太多了,我有点想知道。 同样,如果我在数量上误认为一个可以接管另一个,那么我也想对此进行更正。 即,如果**比x * x更有效,那么我也想知道为什么。
我猜人们使用x*x而不是x**2,因为它在所有语言中均有效,而x**2在Java / C / C ++中则无效。 所以我想大多数例子的原因都是无知。 我很想知道是否存在效率差异/数值差异。
我不同意g.d.d.c,乘法要快得多!
30"""Evaluating the difference in execution time between n*n and n**2"""
from time import time
n = 2
t = time()
for i in range(5000000):
n**2
print("Time for n**2:\t%0.3f" % (time()-t))
t = time()
for i in range(5000000):
n*n
print("Time for n*n:\t%0.3f" % (time()-t))
def test(n):
"""
Difference in execution time between n*n and n**2
within function scope.
"""
t = time()
for i in range(5000000):
n**2
print("Time for n**2:\t%0.3f" % (time()-t))
t = time()
for i in range(5000000):
n*n
print("Time for n*n:\t%0.3f" % (time()-t))
test(n)
结果:
Time for n**2: 2.324496030807495
Time for n*n: 0.5879969596862793
Time for n**2: 2.0771241188049316
Time for n*n: 0.2894318103790283
您可以看到,函数外的乘法运算速度大约快4倍,而函数外的运算速度快7倍。 我无法解释这两个测试之间的区别,也不确定n * n和n ** 2之间的区别,但这可能与Python是一种解释型语言有关,而后者的处理则需要花费一定的时间。 如gddc所示,即使处理器操作非常相似,也需要更多时间。
如果它在一个函数中或在一个函数之外,为什么会有所不同(如此巨大!)?
@moose:最有可能是因为全局变量查找是字典查找,而局部变量查找正在索引数组。
现在我有点困惑了,我发现实际上它确实考虑到了巨大的速度差异,这代表了我的初衷。我不认为这会有很大的不同,也不会导致在函数范围之内或之外。有时候这种奇怪的语言。
@ user2357112你说的很有趣,请您进一步解释一下?我虽然locals()返回了dict以及globals()…
同样,看起来您在Python 3上计时了,而另一个人在Python 2上计时。在这种情况下,Python 3s的bignum指数运算比Python 2s的指数运算差很多。在Python 2上,n**2和n*n的计时几乎相同,如其他答案所示。
@Labo:locals()返回一个dict,但是Python实际上并不将该dict用于局部变量查找。这就是文档说不修改字典的原因之一;它不会影响局部变量的值。
顺便说一句,您使用的是哪个Python 3版本?我对ideone(Python 3是Python 3.4)的测试表明,与乘法相比,幂运算性能有了显着提高。
Python 3.4.3,但3或4几乎相同…
+1代表代码;但您还应该进行切换实验:只需切换n*n和n**2的代码块。特别是对于"全局实验",您会注意到这有所作为。
实际上,两者的总成本可能非常相似:
>>> def s1(x):
... return x * x
...
>>>
>>> def s2(x):
... return x ** 2
...
>>>
>>> from dis import dis
>>>
>>> dis(s1)
2 0 LOAD_FAST 0 (x)
3 LOAD_FAST 0 (x)
6 BINARY_MULTIPLY
7 RETURN_VALUE
>>> dis(s2)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (2)
6 BINARY_POWER
7 RETURN_VALUE
>>>
我认为您可能过早地进行了优化,即使对于数百万或数十亿次的迭代也是如此。 除非您已将此视为瓶颈,否则请使用最适合您的用法。
并且,为完整起见,timeit结果:
>>> timeit.Timer("s1(10)", 'from __main__ import s1').timeit(100000)
0.0186597650628606
>>> timeit.Timer("s2(10)", 'from __main__ import s2').timeit(100000)
0.018789616358585448
这似乎表明x * x在100000次迭代中的速度如此之快。
因此,它本身只是一个样式概念。我一直以为这只是c语言中pow()函数的一部分,因为它进行了函数调用,所以我看到了使用该语言的需要,但是在python中,因为它是内置的。我只是不明白为什么不使用它它。在我看来,只要操作员是已知和理解的,它比其他方法更具表达力。谢谢您的帮助。
对于10e6,它就是那个值,但是它的时间复杂度会成倍增长还是持续增长?我知道在宏伟的计划中,这没什么大不了的,但要做Project Euler Problems,自学Python语言,甚至四分之一秒的时间也让我有些困惑。
没事求幂比常规CPU上的乘法慢得多。您的基准测试没有显示这一点,因为时间是由函数调用(我猜测)或其他动态Python恶作剧的成本所决定的。在编译语言中,差异是巨大的。即使在Python中,我也可以想象在没有函数调用的情况下,它在紧密循环中也有很大的不同,但我没有进行基准测试。无论如何,这(很不幸)与许多应用程序的过早优化相去甚远。
@KonradRudolph:它不是CPU的东西; Python int指数运算不会调用任何CPU指数指令。其所有软件。在Python 2中,即使剥离了函数调用,由于所有其他开销,两者之间的差异约为6%。在Python 3中,相差约为3倍,因为bignum指数代码也无法处理问题。
@ user2357112我看不出这会使事情变得更好。与乘法相比,在软件中实现幂运算会使速度变慢。您的基准测试不足以显示这种差异,因为操作太快,并且计时器的精度相对太低。