2

I see that people usually use the math library to calculate square roots, and I was wondering if there is an advantage (matissa or computational efficiency) over a plain **0.5?

Okay also did a quick test, cpu time tends to be equal

import time 

start_time = time.clock()

i = 0
while i < 10000000: 
    i ** 0.5
    i += 1

elapsed_time = time.clock() - start_time
print ("Time elapsed: {} seconds".format(elapsed_time))

Time elapsed: 7.27 seconds

import time 
import math

start_time = time.clock()

i = 0
while i < 10000000: 
    math.sqrt(i)
    i += 1

elapsed_time = time.clock() - start_time
print ("Time elapsed: {} seconds".format(elapsed_time))

Time elapsed: 7.109999999999999 seconds

  • There is a thread about it on Ubuntu Forums that worth checking out: http://ubuntuforums.org/archive/index.php/t-1444549.html – Eduardo Nov 26 '13 at 20:05
  • Possible duplicate of [Using exponentiation \*\*0.5 less efficient than math.sqrt?](https://stackoverflow.com/questions/6637589/using-exponentiation-0-5-less-efficient-than-math-sqrt) – 200_success Apr 04 '18 at 17:18

5 Answers5

2

Looks like the function call is faster:

In [102]: a = 2

In [103]: timeit a**0.5
1000000 loops, best of 3: 222 ns per loop

In [104]: timeit sqrt(a)
10000000 loops, best of 3: 120 ns per loop

I can't think of any other reason except readability. Which is more readable depends on who you ask, and the context.

jpkotta
  • 9,237
  • 3
  • 29
  • 34
  • That's not a fair comparison-- try `a=2` and then `timeit a**0.5` and `timeit sqrt(a)`. – DSM Nov 26 '13 at 20:06
2

They is a subtle difference in their behavior. x**n first tries x.__pow__(n). If that call returns NotImplemented, then n.__rpow__(x) is called.

>>> (2).__pow__(0.5)
NotImplemented
>>> (0.5).__rpow__(2)
1.4142135623730951

math.sqrt(x) converts x to a float (a C double behind the scenes) and then calls the C math library.

>>> class F(object):
...   def __init__(self, value):
...     self.value = value
...   def __float__(self):
...     print("hi!")
...     return float(self.value)
... 
>>> a=F(2)
>>> math.sqrt(a)
hi!
1.4142135623730951

The difference is usually not important for the normal numeric types in Python but other numeric types can behave differently. gmpy2 implements arbitrary-precision arithmetic for integer and floating point. Values that cause an overflow in math.sqrt() can be handled by **.

>>> import gmpy2
>>> math.sqrt(gmpy2.mpz("1"*999))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: 'mpz' too large to convert to float
>>> gmpy2.mpz("1"*999)**0.5
mpfr('1.0540925533894598e+499')
>>> 
casevh
  • 11,093
  • 1
  • 24
  • 35
1

Without knowing much about python, I would say the operator is better than calling a library function in your case where you're only doing it once simply because using the operator means your interpreter (or compiler in other languages) doesn't have to go through the whole included library.

Isaac
  • 625
  • 1
  • 12
  • 30
0

Based on the description for math.pow(x,[b]) I would hazard that math.sqrt(x) does automatic type casting. In general my guess is the math library is a safer and more reliable function than using **0.5

Dylan Lawrence
  • 1,503
  • 10
  • 32
0

They're about the same:

$ python -m timeit 'import math; [math.sqrt(n) for n in range(100)]'
100000 loops, best of 3: 13.3 usec per loop
$ python -m timeit 'import math; [n**0.5 for n in range(100)]'
100000 loops, best of 3: 16.2 usec per loop
wflynny
  • 18,065
  • 5
  • 46
  • 67