2010-06-15 45 views
11

我想在不使用数学模块的情况下找到数字的平方根,因为我需要调用函数约20k次,并且不希望每次调用函数时都通过链接到数学模块来减慢执行的速度如何在不使用数学模块的情况下执行平方根?

找到平方根有没有更快更简单的方法?

+3

sqrt()s只是很慢。你真的需要找到20k个不同的根,或者你可以使用查找表或缓存结果吗? – 2010-06-15 17:22:07

回答

24

导入数学模块只发生一次,你可能不会比数学模块快得多。还有一个关于Which is faster in Python: x**.5 or math.sqrt(x)?的较旧的Stackoverflow问题。目前还不清楚哪种方法更快。

也许看看NumPySciPy,不一定是sqrt,但如果你正在做一些繁重的计算,他们可能会得心应手。

+8

+1用于回答被问及的问题以及实际需要回答的问题! – Skeolan 2010-06-15 16:42:06

+4

大家知道,使用Numpy数组,并将整个数组提升为.5的能力,在我的测试中,通过迭代相同的numpy数组,可以加速20k平方根至少60倍。 – 2010-06-15 20:38:13

+0

在Mac OS X上使用Python 2.6.5,'sqrt()'实际上更快(请参阅我的答案)。这两种方法实际上是不同的,哪一种更快取决于实现细节。 – EOL 2010-06-16 07:28:41

3

使用电源操作,并提高数字的1/2功率:

>>> 2**0.5 
1.4142135623730951 

至于是否会更快:

>>> timeit.timeit(stmt='sqrt(x)', setup='from math import sqrt; x = 2') 
0.7182440785071833 
>>> timeit.timeit(stmt='x**0.5', setup='from math import sqrt; x = 2') 
0.87514279049432275 
+0

我在我的电脑上得到了类似的结果,但是当我从我接受的问题的接受答案中尝试基准时,math.sqrt更快。这里有一些有趣的事情发生。 – 2010-06-15 16:42:38

+0

这些时间测试不是很有代表性:你可以看到我的答案,它表明'** 0.5'实际上比'math.sqrt'慢。原因是'2 ** 0.5'是一个预先计算的数值常数。 – EOL 2010-06-15 17:21:21

+0

@EOL - 我得到与其他数字相似的结果(即,“0.42521 ** 0.5”大约比“sqrt(0.42521)”快7倍)。我没有得出任何结论,但测试似乎对我有效。 – Seth 2010-06-15 20:54:49

10

至于法比安说,这是很难比快math.sqrt。原因是它使用CPython从C库中调用相应的函数。

from math import sqrt 

到开方以后每次通话将一定要看它的数学模块,从而节省了执行时间:

但是,您可以通过删除属性查找的开销,加快东西:

print sqrt(2) 

这里是定时号码,从最快到最慢的(Python的2.6.5,Mac OS X的10.6.3):sqrt**0.5更快:

[email protected] ~ % python -m timeit -s 'from math import sqrt; x = 2' 'sqrt(x)' 
1000000 loops, best of 3: 0.207 usec per loop 
[email protected] ~ % python -m timeit -s 'x = 2' 'x**0.5' 
1000000 loops, best of 3: 0.226 usec per loop 
[email protected] ~ % 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 -calculated,在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就是要走的路。

6

我想数学图书馆可能会和你自己写的任何东西一样快。但是如果你想自己写,这里有一个算法。我不知道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 
+0

+1实际回答问题:) – 2012-09-26 06:10:01

5

在某些特殊情况下,你可以交易程序大小起泡速度。创建一个大型数组并存储每个平方根操作的预计算结果(使用输入值作为索引)。这是相当有限的,但你不会得到更快。

(这是怎么做到的)

+0

如果这些值都是小整数,这可以工作。如果这些值是任意实数,则这不起作用。此外,这只适用于您希望看到相同的号码多次出现。即使在这样的情况下,我并不是计算输入中可能永远不会显示的数千个数的平方根,而是构建一个缓存并在第一次需要时计算平方根,然后使用缓存中的值。 – Jay 2015-05-08 20:18:12

0

用于计算正方形的Python代码片段。它首先做出初步猜测,如果猜测不够好,它会迭代,直到我们有一个好的猜测。

def gen_square_root_v1(number, epsilon): 

    #boundary condition check 

    if number == '1': 
     return 1 

    elif number <= 0: 
     print('this computes square root for positive numbers only') 

    else: 
     pass 


    prev_estimate = number/2 

    while True: 

     #each itearation, calculate a new estimate 
     new_estimate = (prev_estimate + number/prev_estimate)/2 

     #Alternatively can use if abs(new_estimate - prev_estimate) < epsilon: 

     #check the difference between square of new_estimate and number 
     if abs(new_estimate * new_estimate - number) < epsilon: 
     return prev_estimate 

    #if guess is not good enough, use it to make the next guess   
    prev_estimate = new_estimate 


#call the function  
print(gen_square_root_v1(16,1e-5)) 
相关问题