You're going to find the square root of any number — without using any built-in function. All you need is multiplication, a bit of guessing, and a clever trick that cuts your search in half every time.
Along the way, you'll pick up Python basics: expressions, variables, if-else, loops, and functions — all by solving one real problem.
Open a Jupyter notebook or Google Colab. Use Python as a calculator for every step below — type an expression into a cell and press Shift+Enter to run it.
Type an expression into a cell and press Shift+Enter:
3 * 4
12
Python is your calculator. Now —
What is the square of 2?
(The square of a number is the number multiplied by itself.)
2 * 2
4
What is the square of 3? Of 4? Of 5?
| 3 × 3 | = | 9 |
| 4 × 4 | = | 16 |
| 5 × 5 | = | 25 |
Now reverse the question:
What is the square root of 16? Of 25? Of 9?
Check your answer by squaring your guess in Python.
sqrt(16) = 4, sqrt(25) = 5, sqrt(9) = 3
What is the square root of 5?
It’s not a whole number. But you already know something about it.
| 2 × 2 = 4 | → too small |
| 3 × 3 = 9 | → too big |
So the square root of 5 is between 2 and 3.
Just take a guess!
You know sqrt(5) is between 2 and 3. Let's find it by guessing, checking, and narrowing down.
Check your guess: square it in Python.
guess = 2.5
print(guess * guess)
6.25
6.25 is bigger than 5. Your guess was too high!
So the answer is between 2 and 2.5. Take a better guess!
guess = 2.25
print(guess * guess)
5.0625
Still too high! Answer is between 2 and 2.25.
guess = 2.125
print(guess * guess)
4.515625
Too low! Answer is between 2.125 and 2.25.
Your next guess will be between which two numbers?
Call them lo and hi, then calculate
the midpoint:
lo = 2
hi = 3
guess = (lo + hi) / 2
print(f"Guess: {guess}")
print(f"Guess squared: {guess * guess}")
Guess: 2.5
Guess squared: 6.25
Too high! So the answer is between lo and guess.
Update hi = guess and compute
a new midpoint.
Can you automatically change lo or hi
depending on whether your guess squared was higher or lower than 5?
This is Python’s if-else:
lo = 2
hi = 3
num = 5
guess = (lo + hi) / 2
if guess * guess > num:
# guess was too high — which bound should change?
else:
# guess was too low — which bound should change?
print(f"New range: [{lo}, {hi}]")
lo = 2
hi = 3
num = 5
guess = (lo + hi) / 2
if guess * guess > num:
hi = guess # too high — bring ceiling down
else:
lo = guess # too low — raise the floor
print(f"New range: [{lo}, {hi}]")
New range: [2, 2.5]
Run the logic again and again. Do you see your guess getting closer?
| Round | lo | hi | guess | guess² | |
|---|---|---|---|---|---|
| 1 | 2 | 3 | 2.5 | 6.25 | ↓ too high |
| 2 | 2 | 2.5 | 2.25 | 5.0625 | ↓ too high |
| 3 | 2 | 2.25 | 2.125 | 4.5156 | ↑ too low |
| 4 | 2.125 | 2.25 | 2.1875 | 4.7852 | ↑ too low |
| 5 | 2.1875 | 2.25 | 2.2188 | 4.9231 | ↑ too low |
Each guess cuts the range in half. After 20 rounds, the range is smaller than 0.000001.
But copying this block 20 times is tedious…
Copying and pasting the same block over and over is tedious.
Python's for loop can repeat it for you —
as many times as you want.
Run your logic 20 times using a for loop:
lo = 2
hi = 3
num = 5
for i in range(20):
guess = (lo + hi) / 2
# Use your if-else logic here to update lo or hi
print(f"sqrt({num}) = {guess}")
print(f"guess squared = {guess * guess}")
lo = 2
hi = 3
num = 5
for i in range(20):
guess = (lo + hi) / 2
if guess * guess > num:
hi = guess
else:
lo = guess
print(f"sqrt({num}) = {guess}")
print(f"guess squared = {guess * guess}")
sqrt(5) = 2.2360679774961853
guess squared = 5.000000000000002
Did your guess squared get close to 5? Let’s compare with Python’s built-in:
import math
print(f"Your answer: {guess}")
print(f"math.sqrt(5): {math.sqrt(5)}")
Your answer: 2.2360679774961853
math.sqrt(5): 2.23606797749979
They match! Your simple guessing loop matches the built-in function.
Now repeat the process for square root of 10.
What should lo and
hi start at?
3² = 9 (too small),
4² = 16 (too big) →
lo = 3, hi = 4
Run the same loop — it works!
Every guess eliminates half of the remaining range.
| After 1 guess: | half the range left |
| After 5 guesses: | 1/32 of the range |
| After 10 guesses: | 1/1024 of the range |
| After 20 guesses: | 1/1,048,576 of the range |
This “halving” strategy is called binary search — “binary” because you split the range in two each time.
It is one of the most important algorithms in computer science — and you just invented it.
You've found sqrt(5) and sqrt(10) by repeating the same code with different numbers. Copying code is messy — a function packages it so you can call it with any input.
Consolidate your for-loop and if-else into one function. Fill in the two missing lines:
def mysqrt(num, lo, hi, iterations):
for i in range(iterations):
guess = (lo + hi) / 2
if guess * guess > num:
pass # Your code goes here
else:
pass # Your code goes here
return guess
def mysqrt(num, lo, hi, iterations):
for i in range(iterations):
guess = (lo + hi) / 2
if guess * guess > num:
hi = guess
else:
lo = guess
return guess
When guess * guess > num (too high),
bring the ceiling down: hi = guess.
When too low, raise the floor: lo = guess.
Same logic you’ve been doing all along — now packaged as a reusable function.
Test it:
import math
result = mysqrt(15, 3, 4, 20)
print(f"mysqrt(15): {result}")
print(f"math.sqrt(15): {math.sqrt(15)}")
mysqrt(15): 3.872983346207417
math.sqrt(15): 3.872983346207417
They match!
Try more:
print(mysqrt(5, 2, 3, 20)) # 2.2360679...
print(mysqrt(10, 3, 4, 20)) # 3.1622776...
print(mysqrt(2, 1, 2, 20)) # 1.4142135...
Congratulations! In one sitting you learned:
| Step | What you did | Python concept |
|---|---|---|
| 1 | Computed squares (2×2, 3×3) | Expressions |
| 2 | Reversed the question (sqrt of 16, 25) | Thinking backwards |
| 3 | Guessed sqrt(5), checked by squaring | Variables |
| 4 | Tracked the range with lo and hi | Variables (lo, hi) |
| 5 | Automated the high/low decision | if / else |
| 6 | Repeated the guessing 20 times | for loop |
| 7 | Packaged it as mysqrt | Functions (def) |
The algorithm you built — binary search — doesn’t just work for square roots. It works for cube roots, logarithms, and searching sorted lists. It’s one of the most important algorithms in computer science.
And you just invented it.