11

引自“ Python 编程:计算机科学导论

我们本可以使用求幂 ** 取平方根。使用 math.sqrt 效率更高一些。

“有点”,但在多大程度上,以及如何?

4

5 回答 5

16

从理论上讲,hammar 的答案duffymo 的答案都是很好的猜测。但实际上,在我的机器上,它的效率并不高:

>>> 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
于 2011-07-09T21:35:24.343 回答
11

无需猜测实现,我们可以阅读代码!

math.sqrtsqrt是标准 C 库的一个瘦包装器:参见mathmodule.c第 956 行

运算符根据**参数的类型有多种实现,但在浮点指数的情况下,它最终会pow从标准 C 库中调度(参见floatobject.c第 783 行)。

现代 CPU 通常具有特殊的平方根指令,一般取幂例程不使用这些指令(例如,比较和对比 glibc 和 x86-64 的pow实现sqrt)。但是一旦添加了所有解释器开销(字节码、类型检查、方法分派等),原始速度的差异就不再那么重要了,并且可能会受到诸如是sqrt直接调用还是通过math模块(如其他答案中的时间所示)。

于 2011-07-09T22:28:05.867 回答
1

**必须支持任何指数,而math.sqrt知道它总是0.5math.sqrt因此可以使用更专业(因此可能更有效)的算法。

于 2011-07-09T21:33:50.760 回答
1

我的猜测是 math.sqrt 使用牛顿方法,它以二次方收敛,而求幂使用其他更慢的方法。

于 2011-07-09T21:35:50.513 回答
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

所以数学函数更快......直到你将浮点数转换为整数。(我需要对值做很多比较,虽然我还没有测试过,但比较整数应该比比较浮点数便宜。)

但是,嘿,它是Python。您处于太多抽象之上,无法尝试以这种粒度级别优化性能。

于 2011-12-18T18:13:40.767 回答