Kodeclik Blog

# Python square root

## Square root function in Python

The concept of square roots has been a fundamental part of mathematics for centuries, and it continues to play a crucial role in various fields, including engineering, physics, and computer science.

## Understanding Square Roots

Before diving into the methods for finding square roots in Python, let's briefly review the concept of square roots.

The square root is the inverse of the square function, just like the inverse of the relationship “parent” is the “child” relationship. In other words, we are interpreting the relation between the two entities in the opposite direction.

For instance, 3 squared is 9. The square root of 9 is 3. Well that is not quite right. The square root of 9 can also be -3 (because -3 squared is also 9). But for simplicity sake we say that the square root of 9 is 3 (with the implicit understanding that it could also be negative).

## How to square a number in Python

Before we see how to compute square roots, let us refresh our memory on how to square a number in Python. There are at least three ways to develop a Python square function: we can use the exponent operator ("**"), the in-built pow() function, or the pow() function that is imported from the math module, i.e., the math.pow() function.

Below are three example implementation of the Python square function following the lines above and sample runs to demonstrate how they work.

```
import math as m
def square1(x):
return (x*x)
def square2(x):
return (pow(x,2))
def square3(x):
return (m.pow(x,2))
print(square1(3))
print(square2(3))
print(square3(3))
```

Note that we have three implementations of the square function, namely square1, square2, and square3. The output will be:

```
9
9
9.0
```

Note that the last implementation of the square function, i.e., square3 uses the math library (imported as "m"), and returns a floating point value (even though our input was an integer).

## Three ways to find square roots in Python

Just like the three implementations of a Python square function above, we can have multiple implemenetations of the square root function. One implementation just uses the pow() function, the second uses the math.pow() function, and the third uses the math.sqrt() function. So the first two implementations are parallel to what we saw in the Python square function and the third implementation is a specific function designed for square roots in the Python library. Here is the code to explore all three:

```
import math as m
def squareroot1(x):
return (pow(x,0.5))
def squareroot2(x):
return (m.pow(x,0.5))
def squareroot3(x):
return (m.sqrt(x))
print(squareroot1(9))
print(squareroot2(9))
print(squareroot3(9))
```

Observe that instead of the exponent being 2 (as in the case of the square function), here the exponents are 0.5 (to find square roots). The output is:

```
3.0
3.0
3.0
```

Of these, the Python math.sqrt() built-in function is the preferred one and what we will use for the rest of this blogpost. To summarize, to use this function, you first import the math library and then invoke the sqrt() function in this library.

## Printing the square root of a number

We can use the math.sqrt() function inside a print statement to output user-friendly messages, like so:

```
import math as m
print("The square root of 9 is",m.sqrt(9))
```

The result is:

`The square root of 9 is 3.0`

Note that sqrt() gives the output as a floating point number, which you can convert to integer if necessary. But you have to remember that there are integers for which the square root will be a floating point number. For instance if your input is not a perfect square:

`print(m.sqrt(15))`

The output is:

`3.872983346207417`

## How to test if a number is a perfect square

How can we tell if a number is a perfect square? Simple - we use python sqrt() to compute the square root, convert it to an integer, square it again and see if we get the original number:

```
import math as m
def is_perfect_square(x):
if (int(m.sqrt(x))**2 == x):
return True
else:
return False
print(is_perfect_square(16))
print(is_perfect_square(15))
```

The output is:

```
True
False
```

## Does Python sqrt() understand complex numbers?

In other words, does the sqrt() function in Python return the square root of a negative number? Let's see what happens when we print the square root of a negative number.

```
import math as m
print(m.sqrt(-1))
```

We know that the square root of -1 is the imaginary number often denoted by “i”, but the math module’s sqrt() function does not work with imaginary numbers. So the above code will output:

```
Traceback (most recent call last):
File "main.py", line 3, in <module>
print(m.sqrt(-1))
ValueError: math domain error
```

If you would like to find square roots of negative numbers, you can explore the use of the "cmath" module. The cmath module is a built-in module in Python that contains a variety of complex mathematical functions. In the below program, we first import the cmath module and then use the square root function within this library (which is also called sqrt, but not to be confused with the square root function within the math module).

```
import cmath as m
print(m.sqrt(-1))
```

The output is:

`1j`

where the imaginary number is denoted by the letter "j".

But let us get back to our traditional case where we are given a positive number and we know that the output is going to be a real number.

## Finding the hypotenuse of a right triangle

According to the Pythagorean theorem, in a right triangle, the sum of the squares of the lengths of the two sides is the square of the hypotenuse. So if we know the two smaller sides of a right triangle, we can compute the hypotenuse as follows:

```
import math as m
def find_hyp(a,b):
return(m.sqrt(a**2 + b**2))
print (find_hyp(3,4))
```

This yields:

`5.0`

as expected because 3^2 + 4^2 = 5^2.

## Using sqrt() to check if a triangle is a right triangle

We can apply the same logic to test if a triangle is a right triangle:

```
import math as m
def is_right_triangle(a,b,c):
return (a**2 + b**2 == c**2)
print(is_right_triangle(3,4,5))
print(is_right_triangle(6,8,10))
print(is_right_triangle(1,2,3))
print(is_right_triangle(5,4,3))
```

This yields:

```
True
True
False
False
```

The third answer (False) is because the triangle is not a right triangle. The fourth answer is given as False because we didn’t give the sides in the correct order. If we wanted this to work for any order, we should take the largest value and test if it is the square of the sum of the squares of the other two sides.

Notice that we have not really used the sqrt() function in the above example. Below is a program that uses the square root function in Python to achieve the same result:

```
import math as m
def is_right_triangle(a,b,c):
return (m.sqrt(a**2 + b**2) == c)
print(is_right_triangle(3,4,5))
print(is_right_triangle(6,8,10))
print(is_right_triangle(1,2,3))
print(is_right_triangle(5,4,3))
```

This should yield the same output as above although it is bad programming practice to test for equality between floating point numbers (recall that the square root function in Python will return floating point numbers). The right way to do it would be to see if the difference between the two sides is less than our precision tolerance. (This is left to the reader as an exercise).

## Finding Python square roots in surd notation

What if we don’t care about floating point numbers and instead would like to report square roots as irrational numbers? In other words, we desire to write a square root function in Python that returns the answer in surd notation. For the input of 2, we would like the square root to be printed as:

`√2`

and the square root of 20 to be printed as:

`2√5`

This is called “surd notation”. Let us write a Python program that requests a number from the user as input and prints out the square root in surd notation.

```
import math
#checks if input x is a factor of input y
def is_factor(x,y):
if (math.floor(y/x) == y/x):
return True
else:
return False
#checks if input x is a square number
def is_square_number(x):
if (int(math.sqrt(x)) == math.sqrt(x)):
return True
else:
return False
#finds the greatest square factor
#you can take out of the given number
def find_greatest_square_factor(num):
# creates a variable half of the input num
start_number_squared = math.ceil(num/2)
# creates a variable that is a square of start_number_square
start_number = math.floor(math.sqrt(start_number_squared))
if (start_number == 2):
if (is_factor(4, num)):
return 2
for i in range(start_number,1,-1):
if (is_factor(i**2, num)):
return i
return 1
# final function that actually reduces the square
def reduction_of_the_square(num):
#checks if the inputed number is a square number
if (is_square_number(num)):
return(str(int(math.sqrt(num))))
else:
greatest_factor = find_greatest_square_factor(num)
if (greatest_factor == 1):
return("√" + str(number))
else:
remaining_number = int(num/(greatest_factor**2))
return(str(greatest_factor) + "√" + str(remaining_number))
#taking an input from the player
number = int(input("Enter Number: "))
print(reduction_of_the_square(number))
```

Note how the code is organized. First we have two helper functions which are self-explanatory. Is_factor tests if a number is a factor of another. Is_square_number tests if the input number is a square.

A lot of the magic happens in the next two functions. find_greatest_square_factor tries to find a highest square that is a factor of the original number For this purpose, it starts with half of the given number (because the factor cannot be higher than the square root of this). Then it progressively decreases this estimate to find the largest square.

This function is then used in the main driver function reduction_of_the_square. Here we test for two cases, whether the given number is a square or not. If it is, then we have found the square root as a perfect integer. If not, we factorize out the largest square and place the remaining element under the square root symbol.

Finally, we ask the user for an input number and print the square root in surd notation.

Here is a sample run:

```
Enter Number: 200
10√2
```

Now that we have learnt about square roots and how to compute them using the math.sqrt() function it is time to wonder how these functions calculate square roots in the first place. In other words, how are they able to compute square roots of arbitrary numbers with such precision? Do they use a lookup table? No! That will require enormous storagge to capture all the possible numbers a user can input. Instead they use numerical methods such as the Newton's method and the binary search method.

## Newton's method to find square roots

Newton's method is an iterative technique used to find the roots of a real-valued function. It can also be applied to calculate square roots. The method starts with an initial guess and then refines the estimate in each iteration until it reaches a satisfactory level of accuracy.

To find the square root of a number 'x' using Newton's method, we can use the logic embodied in the below code:

```
epsilon = 1e-10
def newton_square_root(x):
guess = x / 2
while True:
new_guess = 0.5 * (guess + x / guess)
if abs(new_guess - guess) < epsilon:
break
guess = new_guess
return(new_guess)
print(newton_square_root(16))
```

In this example, the epsilon parameter determines the desired level of accuracy. Smaller values of epsilon will result in more precise square root approximations but will require more iterations. Newton's method is a powerful technique for finding square roots and other real roots of functions. It converges quickly to the actual square root and is widely used in mathematical and scientific applications.

For the above code, the output is:

`4.0`

as expected.

## Binary search method to find square roots

Another technique to find the square root of a number is by using a binary search approach. This method involves narrowing down the search range by repeatedly halving it until the desired level of accuracy is achieved. Imagine the binary search method to be akin to playing a hi-lo game. To apply the binary search method, we need to determine the search range and then iteratively update it until we reach the desired accuracy. Consider the below code implementing this idea:

```
epsilon = 1e-10
def binary_search_square_root(x):
low, high = 0, max(1, x)
guess = (low + high) / 2
while True:
square = guess * guess
if abs(square - x) < epsilon:
break
elif square < x:
low = guess
else:
high = guess
guess = (low + high) / 2
return guess
print(binary_search_square_root(16))
```

As you can see in the definition of the binary_search_square_root function, we first set the limits to be 0 and the given number. A guess is made that the square root is the midpoint of this range. If this guess is not accurate (to within the epsilon threshold), we repeatedly re-adjust the range and compute a new guess. In this manner, we narrow down on our square root. The output is:

`4.0`

again as expected. The binary search method is relatively efficient and converges quickly to the actual square root. It is particularly useful when finding square roots of large numbers.

## Finding square roots using the Python Decimal module

Finally, since we are on the topic of numerical calculation of square roots, it is important to present the Python Decimal module. When dealing with floating-point calculations in Python, it's essential to consider potential precision issues due to the way floating-point numbers are represented internally. The decimal module in Python provides an option for higher-precision floating-point arithmetic, which can be helpful when accuracy is critical, such as in financial applications.

Below is sample code using this module

```
from decimal import Decimal, getcontext
precision = 28
def decimal_square_root(x):
getcontext().prec = precision
x_decimal = Decimal(x)
square_root = x_decimal.sqrt()
return float(square_root)
print(decimal_square_root(16))
print(decimal_square_root(17))
```

The output is:

```
4.0
4.123105625617661
```

In this example, we set the precision of the decimal module to 28 digits after the decimal point using getcontext().prec. The sqrt() method of Decimal objects then calculates the square root with the desired precision. The decimal module allows for more control over the precision of calculations, making it suitable for situations where high accuracy is essential.

## Finding square roots using numpy.sqrt()

NumPy is a powerful library for numerical computing in Python. It provides a variety of mathematical functions, including a vectorized square root operation that can efficiently handle arrays and large datasets. To use NumPy for finding square roots, you need to install the library first using a command like "pip install numpy". Once installed you can use numpy to calculate the square root of a single number or even an array:

```
import numpy as np
# Square root of a single number
number = 25
square_root = np.sqrt(number)
print("The square root of", number, "is", square_root)
# Square root of an array of numbers
numbers = np.array([25, 16, 9, 4, 1])
square_roots = np.sqrt(numbers)
print("Square roots of the array:", square_roots)
```

The output is:

```
The square root of 25 is 5.0
Square roots of the array: [5. 4. 3. 2. 1.]
```

NumPy's vectorized operations make it highly efficient for handling large datasets, and it is widely used in scientific and data analysis applications.

In this blog post, we explored various techniques for finding square roots in Python. We started with the math module's sqrt() function, which is the standard and most straightforward approach. We also showed how you can compute square roots in surd notation using a custom-built function. We then delved into more advanced iterative methods like Newton's method and binary search, which offer greater precision and efficiency.

Additionally, we covered the exponentiation operator (**), which provides a simple way to calculate square roots. For higher precision requirements, we introduced the decimal module, and for handling large datasets, we explored the numpy library.

The choice of method depends on the specific use case, precision requirements, and the size of the data you are working with. By understanding all these different options, you can confidently find square roots in Python and apply the most suitable method for your projects.

If you liked learning about square roots in Python, checkout our blogpost on the Python pow() function and computing the greatest common divisor in Python. Also learn how to write a handy Python program to find numbered squares from 1 to 100.

Interested in more things Python? See our blogpost on Python's enumerate() capability. Also if you like Python+math content, see our blogpost on Magic Squares and about the Python isnumeric() method. Finally, master the Python print function!

Want to learn Python with us? Sign up for 1:1 or small group classes.