引自“Python Programming: An Introduction to Computer Science”
我们可以采取平方根 使用指数**。运用 math.sqrt更有效率。
“有点”,但在多大程度上,以及如何?
答案 0 :(得分:16)
从理论上讲,hammar's answer和duffymo's answer是很好的猜测。但实际上,在我的机器上, 更高效:
>>> import timeit
>>> timeit.timeit(stmt='[n ** 0.5 for n in range(100)]', setup='import math', number=10000)
0.15518403053283691
>>> timeit.timeit(stmt='[math.sqrt(n) for n in range(100)]', setup='import math', number=10000)
0.17707490921020508
部分问题是.
操作。如果将sqrt
直接导入命名空间,则会略有改进。
>>> timeit.timeit(stmt='[sqrt(n) for n in range(100)]', setup='from math import sqrt', number=10000)
0.15312695503234863
关键词:轻微。
进一步测试表明,随着数量变大,使用sqrt
带来的好处会增加。但仍然不是很多!
>>> timeit.timeit(stmt='[n ** 0.5 for n in range(1000000)]', setup='import math', number=1)
0.18888211250305176
>>> timeit.timeit(stmt='[math.sqrt(n) for n in range(1000000)]', setup='import math', number=1)
0.18425297737121582
>>> timeit.timeit(stmt='[sqrt(n) for n in range(1000000)]', setup='from math import sqrt', number=1)
0.1571958065032959
答案 1 :(得分:11)
无需猜测实现,我们可以阅读代码!
math.sqrt
是标准C库中sqrt
的精简包装:请参阅mathmodule.c
, line 956
**
运算符具有多个实现,具体取决于参数的类型,但在浮点指数的情况下,它最终从标准C库调度到pow
(请参阅{{ 3}})。
现代CPU通常具有特殊的平方根指令,一般取幂例程不使用(例如,比较和对比glibc中floatobject.c
line 783和pow
的实现,例如x86-64)。但是一旦添加了所有的解释器开销(字节码,类型检查,方法调度等),原始速度的差异并不重要,并且可以由诸如是否直接调用sqrt
或通过math
模块查找(如其他答案中的时间所示)。
答案 2 :(得分:1)
**
必须支持任何指数,math.sqrt
知道它总是0.5
。因此math.sqrt
可以使用更专业(因此可能更有效)的算法。
答案 3 :(得分:1)
我的猜测是math.sqrt使用Newton's method,它以二次方式收敛,而取幂使用其他更慢的东西。
答案 4 :(得分:1)
这是一种略有不同的方法。我们想要一个比平方根大的int。两种方式(对于平方数字不同意,但没关系):
>>>timeit.timeit(stmt='[int(n**0.5)+1 for n in range(1000000)]', setup='', number=1)
0.481772899628
>>>timeit.timeit(stmt='[ceil(sqrt(n)) for n in range(1000000)]', setup='from math import sqrt, ceil', number=1)
0.293844938278
>>>timeit.timeit(stmt='[int(ceil(sqrt(n))) for n in range(1000000)]', setup='from math import sqrt, ceil', number=1)
0.511347055435
所以数学函数更快......直到你将float转换为int。 (我需要对值进行大量比较,虽然我没有测试过,但比较整数应该比比较浮点数便宜。)
但是,嘿,它是 Python 。您可以通过太多的抽象来尝试以这种粒度级别优化性能。