When trying to find a close approximate of the square root of a number bisection algorithms seems to perform extremely well.
In fact bisection search gives a result in just a second for the square root of 10^45
start_time = time.time()
x = 10**45
epsilon = 0.01
numGuesses = 0
low = 0.0
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 - x) >= epsilon:
print('low =', low, 'high =', high, 'ans =', ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print('numGuesses =', numGuesses)
print(ans, 'is close to square root of', x)
elapsed_time = time.time() - start_time
print(elapsed_time)
But when it comes to finding 10**46 it calculates for so long I eventually terminate it...
start_time = time.time()
x = 10**46
epsilon = 0.01
numGuesses = 0
low = 0.0
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 - x) >= epsilon:
print('low =', low, 'high =', high, 'ans =', ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print('numGuesses =', numGuesses)
print(ans, 'is close to square root of', x)
elapsed_time = time.time() - start_time
print(elapsed_time)
Is there any explanation? Can anyone run it?
@Lecagy is correct. The problem is that there are a finite number of floating point numbers. Therefore when you average two that are next to each other, the average is one of the two.
You just need to add a condition to check for this.
import time
start_time = time.time()
x = 10**46
epsilon = 0.01
numGuesses = 0
low = 0.0
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 - x) >= epsilon and ans != low and ans != high:
print('low =', low, 'high =', high, 'ans =', ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print('numGuesses =', numGuesses)
print(ans, 'is close to square root of', x)
elapsed_time = time.time() - start_time
print(elapsed_time)
And now it runs instantly but is not guaranteed to be within epsilon.