A quote from "Python Programming: An Introduction to Computer Science"
We could have taken the square root using exponentiation **. Using math.sqrt is somewhat more efficient.
"Somewhat", but to what extent, and how?
It turns out that the sqrt() function from the standard Python math module is about seven times faster than the corresponding sqrt() function from numpy. As a side note, I learned that it is slightly faster (5-10%) to use the form “from math import sqrt” than it is to use “import math” and “math. sqrt()”.
The interviewer is right. sqrt() is "slow," not slow. Fundamentally, the operation is more complex than an addition or division.
sqrt() function is an inbuilt function in Python programming language that returns the square root of any number. Syntax: math.sqrt(x) Parameter: x is any number such that x>=0 Returns: It returns the square root of the number passed in the parameter.
The return value of sqrt() is the square root of x , as a floating point number. In the example, this would be 5.0 . Let's take a look at some examples of how to (and how not to) use sqrt() .
Theoretically, hammar's answer and duffymo's answer are good guesses. But in practice, on my machine, it's not more efficient:
>>> 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
Part of the problem is the .
operation. If you import sqrt
directly into the namespace, you get a slight improvement.
>>> timeit.timeit(stmt='[sqrt(n) for n in range(100)]', setup='from math import sqrt', number=10000)
0.15312695503234863
Key word there: slight.
Further testing indicates that as the number gets larger, the benefit you get from using sqrt
increases. But still not by a lot!
>>> 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
No need to guess the implementation, we can read the code!
math.sqrt
is a thin wrapper about sqrt
from the standard C library: see mathmodule.c
, line 956
The **
operator has multiple implementations depending on the types of the arguments, but in the case of a floating-point exponent, it eventually dispatches to pow
from the standard C library (see floatobject.c
line 783).
Modern CPUs often have special square root instructions which general exponentiation routines don't use (compare and contrast the implementations of pow
and sqrt
in glibc for x86-64, for example). But once all the interpreter overhead is added (byte codes, type checking, method dispatch etc), the difference in raw speed doesn't matter all that much, and can be dominated by issues like whether you call sqrt
directly or look it up via the math
module (as shown by the timings in other answers).
**
has to support any exponent while math.sqrt
knows it's always 0.5
. math.sqrt
can therefore use a more specialized (and therefore probably more efficient) algorithm.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With