Which is faster in Python: x**.5 or math.sqrt(x)?
math.sqrt(x)
is significantly faster than x**0.5
.
import math
N = 1000000
%%timeit
for i in range(N):
z=i**.5
10 loops, best of 3: 156 ms per loop
%%timeit
for i in range(N):
z=math.sqrt(i)
10 loops, best of 3: 91.1 ms per loop
Using Python 3.6.9 (notebook).
Which is more accurate, x**.5 or math.sqrt(x)?
Neither one is more accurate, they both diverge from the actual answer in equal parts:
>>> (8885558**0.5)**2
8885557.9999999981
>>> sqrt(8885558)**2
8885558.0000000019
>>> 2**1023.99999999999
1.7976931348498497e+308
>>> (sqrt(2**1023.99999999999))**2
1.7976931348498495e+308
>>> ((2**1023.99999999999)**0.5)**2
1.7976931348498499e+308
>>> ((2**1023.99999999999)**0.5)**2 - 2**1023.99999999999
1.9958403095347198e+292
>>> (sqrt(2**1023.99999999999))**2 - 2**1023.99999999999
-1.9958403095347198e+292
http://mail.python.org/pipermail/python-list/2003-November/238546.html
The math module wraps the platform C
library math functions of the same
names;math.pow()
is most useful if
you need (or just want) high
compatibility with C extensions
calling C'spow()
.
__builtin__.pow()
is the implementation of Python's infix**
operator, and deals with complex
numbers, unbounded integer powers, and
modular exponentiation too (the C
pow()
doesn't handle any of those).
** is more complete. math.sqrt
is probably just the C implementation of sqrt which is probably related to pow
.
Python: why are * and ** faster than / and sqrt()?
The (somewhat unexpected) reason for your results is that Python seems to fold constant expressions involving floating-point multiplication and exponentiation, but not division. math.sqrt()
is a different beast altogether since there's no bytecode for it and it involves a function call.
On Python 2.6.5, the following code:
x1 = 1234567890.0 / 4.0
x2 = 1234567890.0 * 0.25
x3 = 1234567890.0 ** 0.5
x4 = math.sqrt(1234567890.0)
compiles to the following bytecodes:
# x1 = 1234567890.0 / 4.0
4 0 LOAD_CONST 1 (1234567890.0)
3 LOAD_CONST 2 (4.0)
6 BINARY_DIVIDE
7 STORE_FAST 0 (x1)
# x2 = 1234567890.0 * 0.25
5 10 LOAD_CONST 5 (308641972.5)
13 STORE_FAST 1 (x2)
# x3 = 1234567890.0 ** 0.5
6 16 LOAD_CONST 6 (35136.418286444619)
19 STORE_FAST 2 (x3)
# x4 = math.sqrt(1234567890.0)
7 22 LOAD_GLOBAL 0 (math)
25 LOAD_ATTR 1 (sqrt)
28 LOAD_CONST 1 (1234567890.0)
31 CALL_FUNCTION 1
34 STORE_FAST 3 (x4)
As you can see, multiplication and exponentiation take no time at all since they're done when the code is compiled. Division takes longer since it happens at runtime. Square root is not only the most computationally expensive operation of the four, it also incurs various overheads that the others do not (attribute lookup, function call etc).
If you eliminate the effect of constant folding, there's little to separate multiplication and division:
In [16]: x = 1234567890.0
In [17]: %timeit x / 4.0
10000000 loops, best of 3: 87.8 ns per loop
In [18]: %timeit x * 0.25
10000000 loops, best of 3: 91.6 ns per loop
math.sqrt(x)
is actually a little bit faster than x ** 0.5
, presumably because it's a special case of the latter and can therefore be done more efficiently, in spite of the overheads:
In [19]: %timeit x ** 0.5
1000000 loops, best of 3: 211 ns per loop
In [20]: %timeit math.sqrt(x)
10000000 loops, best of 3: 181 ns per loop
edit 2011-11-16: Constant expression folding is done by Python's peephole optimizer. The source code (peephole.c
) contains the following comment that explains why constant division isn't folded:
case BINARY_DIVIDE:
/* Cannot fold this operation statically since
the result can depend on the run-time presence
of the -Qnew flag */
return 0;
The -Qnew
flag enables "true division" defined in PEP 238.
Is there any advantage using math.sqrt(num) over num**0.5 in Python
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')
>>>
Python - doing math with built-ins vs math module
If calculating square root of a constant integer, the **
operator maybe several times faster than sqrt
, but when using a variable instead, sqrt
is faster than both **
and math.sqrt
:
In [38]: %timeit -n1000000 3**.5
1000000 loops, best of 3: 46.7 ns per loop
In [39]: %timeit -n1000000 sqrt(3)
1000000 loops, best of 3: 312 ns per loop
In [40]: %timeit -n1000000 math.sqrt(3)
1000000 loops, best of 3: 377 ns per loop
In [41]: x=3
In [42]: %timeit -n1000000 x**.5
1000000 loops, best of 3: 469 ns per loop
In [43]: %timeit -n1000000 sqrt(x)
1000000 loops, best of 3: 327 ns per loop
In [44]: %timeit -n1000000 math.sqrt(x)
1000000 loops, best of 3: 430 ns per loop
How do I calculate square root in Python?
Option 1: math.sqrt()
The math
module from the standard library has a sqrt
function to calculate the square root of a number. It takes any type that can be converted to float
(which includes int
) as an argument and returns a float
.
>>> import math
>>> math.sqrt(9)
3.0
Option 2: Fractional exponent
The power operator (**
) or the built-in pow()
function can also be used to calculate a square root. Mathematically speaking, the square root of a
equals a
to the power of 1/2
.
The power operator requires numeric types and matches the conversion rules for binary arithmetic operators, so in this case it will return either a float
or a complex
number.
>>> 9 ** (1/2)
3.0
>>> 9 ** .5 # Same thing
3.0
>>> 2 ** .5
1.4142135623730951
(Note: in Python 2, 1/2
is truncated to 0
, so you have to force floating point arithmetic with 1.0/2
or similar. See Why does Python give the "wrong" answer for square root?)
This method can be generalized to nth root, though fractions that can't be exactly represented as a float
(like 1/3 or any denominator that's not a power of 2) may cause some inaccuracy:
>>> 8 ** (1/3)
2.0
>>> 125 ** (1/3)
4.999999999999999
Edge cases
Negative and complex
Exponentiation works with negative numbers and complex numbers, though the results have some slight inaccuracy:
>>> (-25) ** .5 # Should be 5j
(3.061616997868383e-16+5j)
>>> 8j ** .5 # Should be 2+2j
(2.0000000000000004+2j)
Note the parentheses on -25
! Otherwise it's parsed as -(25**.5)
because exponentiation is more tightly binding than unary negation.
Meanwhile, math
is only built for floats, so for x<0
, math.sqrt(x)
will raise ValueError: math domain error
and for complex x
, it'll raise TypeError: can't convert complex to float
. Instead, you can use cmath.sqrt(x)
, which is more more accurate than exponentiation (and will likely be faster too):
>>> import cmath
>>> cmath.sqrt(-25)
5j
>>> cmath.sqrt(8j)
(2+2j)
Precision
Both options involve an implicit conversion to float
, so floating point precision is a factor. For example:
>>> n = 10**30
>>> x = n**2
>>> root = x**.5
>>> n == root
False
>>> n - root # how far off are they?
0.0
>>> int(root) - n # how far off is the float from the int?
19884624838656
Very large numbers might not even fit in a float and you'll get OverflowError: int too large to convert to float
. See Python sqrt limit for very large numbers?
Other types
Let's look at Decimal
for example:
Exponentiation fails unless the exponent is also Decimal
:
>>> decimal.Decimal('9') ** .5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ** or pow(): 'decimal.Decimal' and 'float'
>>> decimal.Decimal('9') ** decimal.Decimal('.5')
Decimal('3.000000000000000000000000000')
Meanwhile, math
and cmath
will silently convert their arguments to float
and complex
respectively, which could mean loss of precision.
decimal
also has its own .sqrt()
. See also calculating n-th roots using Python 3's decimal module
Python - doing math with built-ins vs math module
If calculating square root of a constant integer, the **
operator maybe several times faster than sqrt
, but when using a variable instead, sqrt
is faster than both **
and math.sqrt
:
In [38]: %timeit -n1000000 3**.5
1000000 loops, best of 3: 46.7 ns per loop
In [39]: %timeit -n1000000 sqrt(3)
1000000 loops, best of 3: 312 ns per loop
In [40]: %timeit -n1000000 math.sqrt(3)
1000000 loops, best of 3: 377 ns per loop
In [41]: x=3
In [42]: %timeit -n1000000 x**.5
1000000 loops, best of 3: 469 ns per loop
In [43]: %timeit -n1000000 sqrt(x)
1000000 loops, best of 3: 327 ns per loop
In [44]: %timeit -n1000000 math.sqrt(x)
1000000 loops, best of 3: 430 ns per loop
Related Topics
How to Use Pip to Install a Package from a Private Github Repository
How to Separate the Functions of a Class into Multiple Files
Python Beautifulsoup Extract Text Between Element
Python Method for Reading Keypress
Runtimeerror: Main Thread Is Not in Main Loop
How to Access Pandas Groupby Dataframe by Key
How Does _Contains_ Work for Ndarrays
When Should I Subclass Enummeta Instead of Enum
Check List of Words in Another String
Generating Matplotlib Graphs Without a Running X Server
How to Prevent Python's Urllib(2) from Following a Redirect
Is There a "Not Equal" Operator in Python
Generate a Random Letter in Python
In Python, How to Convert Seconds Since Epoch to a 'Datetime' Object