Babylonian algorithm function using while loop - python

I am struggling on a Babylonian algorithm to find a square root of 'a':
Take a guess: pick some number x.
Check how good is our guess, by computing abs(x2 - a). If it’s close enough (for example, less than 10^-6), we’re done.
Otherwise, calculate an improved guess (x + a/x) / 2; this replaces the previous value of x and we repeat from the test.
I have no idea where the while loop should come to, and what to do if the improved guess is still not correct.
I have tried to every code under the 'while True' loop, but that made it even more confusing. This is the draft code below:
def babylonian(a,x):
difference = abs(x ** 2 - a)
improved_guess = 0.5 * (a / x + x)
if difference < 10 ** -6:
print("Guess is right")
while difference > 10 ** -6:
if (improved_guess ** 2 - a) < 10 ** -6:
break
If I enter (4, 1) for instance, the terminal does not give any value.

According to you algorithm first find the difference using initial guess if it is ok then while loop wont execute if not the find the appropriate guess inside while loop an you have to return the final guess from the function:
def babylonian(a,x):
difference = abs(x ** 2 - a)
if difference < 10 ** -6:
print("Guess is right")
while difference > 10 ** -6:
x = 0.5 * (a / x + x)
difference = abs(x ** 2 - a)
return x

Follow your recipe:
TOLERANCE = 1e-6
def babylonian(target, guess): # Take a guess
# Check how good is our guess, by computing abs(x2 - a).
# If it’s close enough (for example, less than 10^-6), we’re done.
while abs(guess*guess - target) > TOLERANCE:
print(guess)
# Otherwise, calculate an improved guess (x + a/x) / 2;
new_guess = (guess + target/guess) / 2
# this replaces the previous value of x
guess = new_guess
# and we repeat from the test.
return guess

Make following changes to your code:
def Babylonian(a, x):
difference = abs(x ** 2 - a)
if difference < 0.000001:
print("Correct", x)
else:
while difference > 0.000001:
x = 0.5 * (x + a/x)
difference = abs(x ** 2 - a)
print("Correct ", x)
You need to update the value of x in the while loop, otherwise it will go into an infinite loop.

Related

Newton's method of succesive approximations

I was trying to build a program to based on the inputs use Newton's method of successive approximations and calculate the answer, using while and if statements, but after running the program, it only collects the input from the user and do not follow up with anything.
I would really appreciate some help.
x = float(input("Number you want to know, the square root of: "))
y = float(input("What is your guess ? "))
z = float
a = float
while (True):
if (abs(y - x) < 0.001):
print (y)
break
else:
z = (x / y)
a = ((z + y)/2)
y = a
Consider the case where you want to know the square root of 2. So x will be 2 and y will approach the correct answer. x never changes here, so when will abs(√2 - 2) even be less than 0.001? Then answer is never, which is why your code never exists the loop.
You should be comparing the previous estimate to the new estimate and stopping when the updated value is lower than you tolerance. For example:
x = 2
y = 1
while (True):
print (y)
a = ((x / y + y)/2)
if abs(y - a) < .000001: # has the estimate changed enough?
break
y = a
Will quickly converge, printing:
1
1.5
1.4166666666666665
1.4142156862745097
1.4142135623746899
you can try :
while(True):
if (abs(y*y - x) < 0.001)

Simpson's Rule Takes Forever to Run in Python

I've written the following function for estimating the definite integral of a function with Simpson's Rule:
def fnInt(func, a, b):
if callable(func) and type(a) in [float] and type(b) in [float]:
if a > b:
return -1 * fnInt(func, b, a)
else:
y1 = nDeriv(func)
y2 = nDeriv(y1)
y3 = nDeriv(y2)
y4 = nDeriv(y3)
f = lambda t: abs(y4(t))
k = f(max(f, a, b))
n = ((1 / 0.00001) * k * (b - a) ** 5 / 180) ** 0.25
if n > 0:
n = math.ceil(n) if math.ceil(n) % 2 == 0 else math.ceil(n) + 1
else:
n = 2
x = (b - a) / n
ans = 0
for i in range(int((n - 4) / 2 + 1)):
ans += (x / 3) * (4 * func(a + x * (2 * i + 1)) + 2 * func(a + x * (2 * i + 2)))
ans += (x / 3) * (func(a) + 4 * func(a + x * (n - 1)) + func(b))
return ans
else:
raise TypeError('Data Type Error')
It seems, however, that whenever I try to use this function, it takes forever to produce an output. Is there a way that I can rewrite this code in order to take up less time?
As one of the comments mentioned, profiling the code will show you the slowdowns. Perhaps nDeriv is slow. If you don't have a profiling tool, you can put time() calls around each section of code and print the results. More info here: Measure time elapsed in Python?
So, if the slowdown ends up being in your for loop, here are a few things you can try:
Python might be computing the loop condition every iteration:
for i in range(int((n - 4) / 2 + 1)):
calculate int((n - 4) / 2 + 1) once before the loop.
Don't recalculate stuff inside the loops that doesn't change. For example, x / 3 is going to be recalculated every loop iteration, but it never changes. Do it before the loop starts.
Likewise, you're doing 2 * i twice every loop iteration.
Addition is faster than multiplication. The func arguments could be re-written as:
xi = x * i
a1 = a + xi + xi + x
a2 = a1 + x
and then taking it a step further, you could also re-do xi as an accumulator. That is, start with x = 0, then every iteration simply x += x
This is probably obvious, but if func() is difficult to calculate, this function will be exponentially slow.
Python may be doing a lot of simpler optimizations for you, so these may not help, but just wanted to share some ideas.

Square Root using Babylonian Method returns wrong value

Trying to use a loop function to find the square root of a number.
I'm trying to use the Babylonian method but it will not return the correct answer. If someone could point out where I have an error that would be much appreciated.
def sqrt(number, guess, threshold):
x = number / 2
prev_x = x + 2 * threshold
while abs(prev_x - x) > threshold:
prev_x = x
x = (x + guess / x) / 2
square_root = x
return square_root
test = sqrt(81, 7, 0.01)
print (test)
Change
x = (x+guess/x)/2
as this would progress to square root of guess. Change it to
x = (x+number/x)/2
Move return statement out of the while loop
initialize x to guess instead of number/2
There's no need for a guess variable at all. Your x = number/2 is your initial guess already, and by using an arbitrarily assigned guess in your computation without updating it you certainly would not get the right number.
Replace guess with number instead, and return only when the while loop is finished, and your code would work:
def sqrt(number,guess,threshold):
x = number/2
prev_x = x+2*threshold
while abs(prev_x-x)>threshold:
prev_x = x
x = (x+number/x)/2
square_root = x
return square_root
To actually make use of guess you should keep updating it as you approximate the square root:
def sqrt(number,guess,threshold):
while abs(guess - number / guess) > threshold:
guess = (guess + number / guess) / 2
return guess

Incorrect answer while calculating pi value from given series

I was trying to calculate value of pi using this formula:
I had written this code for finding it for a given n:
def pisum(n):
sum=3.0
x=2.0
while (n>0):
if n%2==1:
sum=sum+(4/(x*(x+1)*(x+2)))
else :
sum=sum-(4/(x*(x+1)*(x+2)))
x=x+2
n=n-1
return str(sum)
It runs fine for n=0 and n=1 and gives output 3.0, 3.16666666667. But for n=50 the output should be 3.1415907698497954 but it is giving 2.85840923015. Why so much difference? Please help to correct if i had done something wrong.
The problem is that you are using n%2 in order to determine whether to subtract or add. It is not the amount of loops that you start with that should matter, but which loop you're in. To see that, try using your function for an odd number, e.g. 51 and you will see that it will give you a correct answer.
To explain further, if you start with n=50, you will initially subtract (4/(x*(x+1)*(x+2))) from 3 rather than add to it, but if you start with n=51, you will initially add.
If you modify your function as follows:
def pisum(n):
sum = 3.0
x = 2.0
for i in range(n):
if i % 2 == 0:
sum = sum + (4 / (x * (x + 1) * (x + 2)))
else:
sum = sum - (4 / (x * (x + 1) * (x + 2)))
x = x + 2
return str(sum)
you will always get a correct result.
You made a small mistake.
One correct program:
def pisum(n):
sum = 3.
for i in xrange(2, 2*n+2, 2):
sum += (4. if (i&2) == 2 else -4.)/i/(i+1)/(i+2)
return sum
Being more conservative with number of lines:
def pisum(n):
return 3. + sum([(4. if (i&2) == 2 else -4.)/i/(i+1)/(i+2) for i in xrange(2,2*n+2,2)])
Mistake in yours:
You are iterating on n in reverse, thus one time (odd value of n) you are calculating:
and for another value of n (even value apart from 0) you are calculating

Python, square root function?

I have compiled multiple attempts at this and have failed miserably, some assistance would be greatly appreciated.
The function should have one parameter without using the print statement. Using Newton's method it must return the estimated square root as its value. Adding a for loop to update the estimate 20 times, and using the return statement to come up with the final estimate.
so far I have...
from math import *
def newton_sqrt(x):
for i in range(1, 21)
srx = 0.5 * (1 + x / 1)
return srx
This is not an assignment just practice. I have looked around on this site and found helpful ways but nothing that is descriptive enough.
This is an implementation of the Newton's method,
def newton_sqrt(val):
def f(x):
return x**2-val
def derf(x):
return 2*x
guess =val
for i in range(1, 21):
guess = guess-f(guess)/derf(guess)
#print guess
return guess
newton_sqrt(2)
See here for how it works. derf is the derivative of f.
I urge you to look at the section on Wikipedia regarding applying Newton's method to finding the square root of a number.
The process generally works like this, our function is
f(x) = x2 - a
f'(x) = 2x
where a is the number we want to find the square root of.
Therefore, our estimates will be
xn+1 = xn - (xn2 - a) / (2xn)
So, if your initial guess is x<sub>0</sub>, then our estimates are
x1 = x0 - (x02 - x) / (2x0)
x2 = x1 - (x12 - x) / (2x1)
x3 = x2 - (x22 - x) / (2x2)
...
Converting this to code, taking our initial guess to be the function argument itself, we would have something like
def newton_sqrt(a):
x = a # initial guess
for i in range(20):
x -= (x*x - a) / (2.0*x) # apply the iterative process once
return x # return 20th estimate
Here's a small demo:
>>> def newton_sqrt(a):
... x = a
... for i in range(20):
... x -= (x*x - a) / (2.0*x)
... return x
...
>>> newton_sqrt(2)
1.414213562373095
>>> 2**0.5
1.4142135623730951
>>>
>>> newton_sqrt(3)
1.7320508075688774
>>> 3**0.5
1.7320508075688772
In your code you are not updating x (and consequently srx) as you loop.
One problem is that x/1 is not going to do much and another is that since x never changes all the iterations of the loop will do the same.
Expanding on your code a bit, you could add a guess as a parameter
from math import *
def newton_sqrt(x, guess):
val = x
for i in range(1, 21):
guess = (0.5 * (guess + val / guess));
return guess
print newton_sqrt(4, 3) # Returns 2.0
You probably want something more like:
def newton_sqrt(x):
srx = 1
for i in range(1, 21):
srx = 0.5 * (srx + x/srx)
return srx
newton_sqrt(2.)
# 1.4142135623730949
This both: 1) updates the answer at each iteration, and 2) uses something much closer to the correct formula (ie, no useless division by 1).

Categories