如何不使用math模块计算平方根?
我想要找到一个数字的平方根,但不想使用数学模块,因为我需要调用这个函数大约2万次,不想每次调用时都链接数学模块,这样会让执行速度变慢。
有没有更快更简单的方法来计算平方根呢?
11 个回答
12
我觉得数学库的速度应该和你自己写的代码差不多快。不过,如果你想自己写一个算法,这里有一个例子。我不太懂Python,所以我就写了一些伪代码。
function sqrt(x)
lastGuess=x/2
loop
guess=(lastGuess+x/lastGuess)/2
if abs(guess-lastGuess)<.000001 // or whatever threshold you want
exit loop
lastGuess=guess
return guess
然后把这个伪代码转成Python代码:
def sqrt(x):
last_guess= x/2.0
while True:
guess= (last_guess + x/last_guess)/2
if abs(guess - last_guess) < .000001: # example threshold
return guess
last_guess= guess
12
正如Fabian所说,想要比math.sqrt
更快是很难的。原因是它调用了C语言库中的相应函数,这在CPython中是这样实现的。
不过,你可以通过去掉查找属性的开销来加快速度:
from math import sqrt
每次后续调用sqrt时,就不需要再去math模块中查找,这样可以节省执行时间:
print sqrt(2)
这里有一些时间测试的数据,从最快到最慢(Python 2.6.5,Mac OS X 10.6.3):sqrt
比**0.5
要快:
lebigot@weinberg ~ % python -m timeit -s 'from math import sqrt; x = 2' 'sqrt(x)'
1000000 loops, best of 3: 0.207 usec per loop
lebigot@weinberg ~ % python -m timeit -s 'x = 2' 'x**0.5'
1000000 loops, best of 3: 0.226 usec per loop
lebigot@weinberg ~ % python -m timeit -s 'import math; x = 2' 'math.sqrt(x)'
1000000 loops, best of 3: 0.268 usec per loop
注意,时间测试是计算一个变量的平方根。它们并不是计算像2**0.5
这样的常量,因为2**0.5
在CPython中是预先计算好的:
import dis
def f():
return 2**0.5
print dis.dis(f)
打印结果
2 0 LOAD_CONST 3 (1.4142135623730951)
3 RETURN_VALUE
你会看到常量浮点数sqrt(2) = 1.414…
如果你在处理数字数组,使用NumPy的sqrt
会更合适,正如另一个回答中提到的那样。
33
导入数学模块只需要做一次,而且你可能找不到比数学模块更快的方式了。还有一个旧的Stackoverflow问题讨论了在Python中,x**.5和math.sqrt(x)哪个更快?,但目前还不清楚哪种方法更快。