17

I want to find the square root of a number without using the math module,as i need to call the function some 20k times and dont want to slow down the execution by linking to the math module each time the function is called

Is there any faster and easier way for finding square root?

1
  • 3
    sqrt()s are just slow. Do you really need to find 20k distinct roots, or can you use a lookup table or cache results? Commented Jun 15, 2010 at 17:22

11 Answers 11

33

Importing the math module only happens once, and you probably won't get much faster than the math module. There is also an older Stackoverflow question regarding Which is faster in Python: x**.5 or math.sqrt(x)?. It is not clear which method is faster.

Maybe take a look at NumPy and SciPy, not necessarily for the sqrt but if you're doing some heavy calculations they could be handy.

Sign up to request clarification or add additional context in comments.

4 Comments

+1 for answering both the question being asked and the question that actually needed answering!
Just so you know, using a Numpy array and just raising the whole array to the .5 power speeds up 20k square roots by a factor of at least 60x in my tests over iterating over the same numpy array.
With Python 2.6.5 on Mac OS X, sqrt() is actually faster (see my answer). The two approaches are actually different, and which one is faster depends on implementation details.
I've removed the text about which is faster.
12

I'd think the math library would likely be as fast as anything you could write yourself. But if you want to write your own, here's one algorithm. I don't know Python, so I'll just write some pseudo-code.

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 

and the pseudocode translated to 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 

1 Comment

Babyloian Method C++ version at stackoverflow.com/a/40528142/5595995
12

As Fabian said, it's hard to be faster than math.sqrt. The reason is that it calls the correspond function from the C library, with CPython.

However, you can speed things up by removing the overhead of attribute lookup:

from math import sqrt 

Each subsequent call to sqrt will not have to look it up in the math module, which saves execution time:

print sqrt(2) 

Here are timing numbers, from the fastest to the slowest (Python 2.6.5, Mac OS X 10.6.3): sqrt is faster than **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 

Note that the timing tests calculate the square root of a variable. They do not calculate a constant like 2**0.5, because 2**0.5 is pre-calculated, in CPython:

import dis def f(): return 2**0.5 print dis.dis(f) 

prints

2 0 LOAD_CONST 3 (1.4142135623730951) 3 RETURN_VALUE 

where you see the constant float sqrt(2) = 1.414…

If you manipulate arrays of numbers, NumPy's sqrt is the way to go, as mentioned in another answer.

4 Comments

Is it really running the code in each iteration and not caching it in any way? I am so amazed by the performance of this, I tried with 10 (8.04 ns), 10000 (8.18 ns), 10000000 (8.31 ns), 10000000000 (8.23 ns) and it seems like constant time to me. Now I am not sure about this way, am I missing something? Is it really (near) constant time ?
I guess that you're listing a number of iterations? What is your exact test code?
Here is python -m timeit -s 'import math; x= 10000000000; math.sqrt(x)'
The algorithm used for calculating the square root might indeed well be running in constant time, so the timing results you observe do not shock me This is for instance possible for 32-bit floats (en.m.wikipedia.org/wiki/Fast_inverse_square_root).
7

You should type this line inside Jupyter Notebook:

25**(1/2) 

Comments

5

In some special cases you can trade program size for blistering speed. Create a large array and store the pre-calculated result for every square root operation (using the input value as the index). It's pretty limited but you won't get anything faster.

(That's how quake did it)

1 Comment

If the values are all small integers, this could work. If the values are arbitrary real numbers, this will not work. Also, this only works if you expect to see the same number show up many times. Even at that, rather than calculating the square roots of thousands of numbers that may never show up in the input, I'd build a cache and calculate the square root the first time it's needed, then after that use the value from the cache.
4

Use the power operator, and raise your numbers to the 1/2 power:

>>> 2**0.5 1.4142135623730951 

As to whether it's faster:

>>> 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 

5 Comments

I get similar results on my computer, but when I try the benchmark from the accepted answer of the question I linked to, math.sqrt is faster. There is something funny going on here.
These timing tests are not very representative: you can see my answer, which shows that '**0.5' is actually slower than math.sqrt. The reason is that 2**0.5 is a pre-calculated numerical constant.
@EOL - I get similar results with other numbers (i.e., 0.42521**0.5 is roughly 7 times faster than sqrt(0.42521)). I'm not making any conclusions, but the test seems valid to me.
You do get the same result because 0.42521**0.5 is pre-compiled by Python (as is any constant to the power 0.5): when you run the code, no mathematical operation is performed; instead, Python just loads a constant number (see the disassembled code in my answer). If computation time matters, it's only when the square root of variables is calculated (not of constants); so, realistic tests should involve taking the square root of a variable.
I'm being dense, I get it now. Thanks :P Fixed the test.
3

You could implement Newton's method but, though it's really fast, it's unlikely to be faster than the C version which I assume is implemented in the math module. See http://en.wikipedia.org/wiki/Methods_of_computing_square_roots .

Comments

2

Square Root Function

 def sqrt(number): if number ** 0.5 == int(number ** 0.5): return True else: return False 

Comments

2

bit too late to the party, but anyways I would like to mention these simple arithmetics:

25**(1/2) 

or

pow(25, 0.5) 

This will return as 5.0 Enjoy.

Comments

0

Python code snippet for computing square. It first makes an initial guess, and if the guess is not good enough it iterates until we have a good guess

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)) 

1 Comment

What is this? This isn't what the OP has asked.
0

the below code is to find the square root of a number without using built in methods using python.the code is very simple to understand because i wrote the code using mathematics simple solution.

 x=float(input()) min1=0 max1=x for i in range(10): mid=(min1+max1)/2 #middle value res=mid**2 #finding the square of middle value if res==x: #if the middle value is square root program break here break elif res>x: #if the square value of the middle value is more than x then we need to take max value as middle max1=mid else: #if the square value of the middle value is less than x then we need to take min value as middle min1=mid print(mid) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.