Sqrt($x$)
I came across a fun exercise on LeetCode, where you have to calculate $f(x) = \sqrt{x}$, without using the standard library functions such as Math.Pow
or x**0.5
. Wikipedia has plenty of implementations to solve this problem efficiently, but I figured it would be a nice challenge to come up with a solution of my own.
My approach was to determine a upper and a lower bound, and do a binary search to find the solution. Let $L$ be the lower bound. Since we know that a square root function requires that $x > 0$, we can set $L = 0$. Likewise, let $U$ be the upper bound. We know that $\sqrt x < x$ (if $x > 1$), which we use to define the upper bound $U = \max(1, x)$.
Now we are going to guess what $\sqrt x$ is. We know that $\sqrt{x}$ lies between $L < \sqrt x < U$. Let $k$ be our guess and initially set this to $k = \frac{L + U}{2}$.
Next we calculate the error of our guess, which we can do with $\left|\ \sqrt{x} - k\ \right| \leq \epsilon$. However, because we cannot calculate square root functions, we need to square it and compare $k^2$ with $x$, giving $\left|\ x - k^2\ \right| \leq \epsilon$.
While the error is bigger than $\epsilon$, we need to adjust our guess. We do this by comparing $k^2$ to $x$.
- If $x < k^2$ then we adjust the upper bound and set it to $U = k$.
- If $x > k^2$ then we adjust the lower bound and set it to $L = k$.
public class Solution {
public int MySqrt(int x) {
double lowerBound = 0;
double upperBound = Math.Max(1, x);
double guess = (upperBound + lowerBound) / 2;
double epsilon = 0.1;
while (Math.Abs(guess * guess - x) > epsilon || guess * guess < x) {
double guess2 = guess * guess;
if (x < guess2) {
upperBound = guess;
}
if (x > guess2) {
lowerBound = guess;
}
guess = (upperBound + lowerBound) / 2;
}
return (int)guess;
}
}
The extra check guess * guess < x
ensures that we are always over estimating $x$ and getting the correct answer after truncating the output.