I need to calculate the square root of a number, for example √9 = 3 or √2 = 1.4142. How can I do it in Python?
The inputs will probably be all positive integers, and relatively small (say less than a billion), but just in case they're not, is there anything that might break?
Note: This is an attempt at a canonical question after a discussion on Meta about an existing question with the same title.
Related
- Integer square root in python
- Is there a short-hand for nth root of x in Python?
- Difference between **(1/2), math.sqrt and cmath.sqrt?
- Why is math.sqrt() incorrect for large numbers?
- Python Sqrt Limit?
- Which is faster in Python: x**.5 or math.sqrt(x)?
- Why does Python give the "wrong" answer for square root? (specific to Python 2)
- calculating n-th roots using Python 3's decimal module
- How can I take the square root of -1 using python? (focused on NumPy)
CodePudding user response:
Option 1: Fractional exponent
>>> 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:
>>> 8 ** (1/3)
2.0
Option 2: math.sqrt()
>>> import math
>>> math.sqrt(9)
3.0
Edge cases
Negative and complex
Exponentiation works with negative numbers and complex numbers, though the results are very slightly off and I'm not sure why:
>>> (-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 negative.
Meanwhile, math is only built for floats, so for x<0, math.sqrt 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:
>>> 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
>>> square = n**2
>>> x = square**.5
>>> x == n
False
>>> x - n # how far off are they?
0.0
>>> int(x) - 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?
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
CodePudding user response:
NumPy
>>> import numpy as np
>>> np.sqrt(25)
5.0
>>> np.sqrt([2, 3, 4])
array([1.41421356, 1.73205081, 2. ])
For negative inputs, it'll return nan, so np.lib.scimath.sqrt() is available for that case.
>>> a = [4, -1, np.inf]
>>> np.sqrt(a)
<stdin>:1: RuntimeWarning: invalid value encountered in sqrt
array([ 2., nan, inf])
>>> np.lib.scimath.sqrt(a)
array([ 2. 0.j, 0. 1.j, inf 0.j])
