Finding the square root using Newton's method (errors!) - python

I'm working to finish a math problem that approximates the square root of a number using Newton's guess and check method in Python. The user is supposed to enter a number, an initial guess for the number, and how many times they want to check their answer before returning. To make things easier and get to know Python (I've only just started learning the language a couple of months ago) I broke it up into a number of smaller functions; the problem now, though, is that I'm having trouble calling each function and passing the numbers through.
Here is my code, with comments to help (each function is in order of use):
# This program approximates the square root of a number (entered by the user)
# using Newton's method (guess-and-check). I started with one long function,
# but after research, have attempted to apply smaller functions on top of each
# other.
# * NEED TO: call functions properly; implement a counting loop so the
# goodGuess function can only be accessed the certain # of times the user
# specifies. Even if the - .001 range isn't reached, it should return.
# sqrtNewt is basically the main, which initiates user input.
def sqrtNewt():
# c equals a running count initiated at the beginning of the program, to
# use variable count.
print("This will approximate the square root of a number, using a guess-and-check process.")
x = eval(input("Please type in a positive number to find the square root of: "))
guess = eval(input("Please type in a guess for the square root of the number you entered: "))
count = eval(input("Please enter how many times would you like this program to improve your initial guess: "))
avg = average(guess, x)
g, avg = improveG(guess, x)
final = goodGuess(avg, x)
guess = square_root(guess, x, count)
compare(guess, x)
# Average function is called; is the first step that gives an initial average,
# which implements through smaller layers of simple functions stacked on each
# other.
def average(guess, x) :
return ((guess + x) / 2)
# An improvement function which builds upon the original average function.
def improveG(guess, x) :
return average(guess, x/guess)
# A function which determines if the difference between guess X guess minus the
# original number results in an absolute vale less than 0.001. Not taking
# absolute values (like if guess times guess was greater than x) might result
# in errors
from math import *
def goodGuess(avg, x) :
num = abs(avg * avg - x)
return (num < 0.001)
# A function that, if not satisfied, continues to "tap" other functions for
# better guess outputs. i.e. as long as the guess is not good enough, keep
# improving the guess.
def square_root(guess, x, count) :
while(not goodGuess(avg, x)):
c = 0
c = c + 1
if (c < count):
guess = improveG(guess, x)
elif (c == count):
return guess
else :
pass
# Function is used to check the difference between guess and the sqrt method
# applied to the user input.
import math
def compare(guess, x):
diff = math.sqrt(x) - guess
print("The following is the difference between the approximation")
print("and the Math.sqrt method, not rounded:", diff)
sqrtNewt()
Currently, I get this error: g, avg = improveG(guess, x)
TypeError: 'float' object is not iterable.
The final function uses the final iteration of the guess to subtract from the math square root method, and returns the overall difference.
Am I even doing this right? Working code would be appreciated, with suggestions, if you can provide it. Again, I'm a newbie, so I apologize for misconceptions or blind obvious errors.

Implementation of the newton method:
It should be fairly easy to add little tweaks to it when needed. Try, and tell us when you get stuck.
from math import *
def average(a, b):
return (a + b) / 2.0
def improve(guess, x):
return average(guess, x/guess)
def good_enough(guess, x):
d = abs(guess*guess - x)
return (d < 0.001)
def square_root(guess, x):
while(not good_enough(guess, x)):
guess = improve(guess, x)
return guess
def my_sqrt(x):
r = square_root(1, x)
return r
>>> my_sqrt(16)
4.0000006366929393
NOTE: you will find enough exaples on how to use raw input here at SO or googling, BUT, if you are counting loops, the c=0 has to be outside the loop, or you will be stuck in an infinite loop.
Quiqk and dirty, lots of ways to improve:
from math import *
def average(a, b):
return (a + b) / 2.0
def improve(guess, x):
return average(guess, x/guess)
def square_root(guess, x, c):
guesscount=0
while guesscount < c :
guesscount+=1
guess = improve(guess, x)
return guess
def my_sqrt(x,c):
r = square_root(1, x, c)
return r
number=int(raw_input('Enter a positive number'))
i_guess=int(raw_input('Enter an initial guess'))
times=int(raw_input('How many times would you like this program to improve your initial guess:'))
answer=my_sqrt(number,times)
print 'sqrt is approximately ' + str(answer)
print 'difference between your guess and sqrt is ' + str(abs(i_guess-answer))

The chosen answer is a bit convoluted...no disrespect to the OP.
For anyone who ever Googles this in the future, this is my solution:
def check(x, guess):
return (abs(guess*guess - x) < 0.001)
def newton(x, guess):
while not check(x, guess):
guess = (guess + (x/guess)) / 2.0
return guess
print newton(16, 1)

Here's a rather different function to compute square roots; it assumes n is non-negative:
def mySqrt(n):
if (n == 0):
return 0
if (n < 1):
return mySqrt(n * 4) / 2
if (4 <= n):
return mySqrt(n / 4) * 2
x = (n + 1.0) / 2.0
x = (x + n/x) / 2.0
x = (x + n/x) / 2.0
x = (x + n/x) / 2.0
x = (x + n/x) / 2.0
x = (x + n/x) / 2.0
return x
This algorithm is similar to Newton's, but not identical. It was invented by a Greek mathematician named Heron (his name is sometimes spelled Hero) living in Alexandria, Egypt in the first century (about two thousand years ago). Heron's recurrence formula is simpler than Newton's; Heron used x' = (x + n/x) / 2 where Newton used x' = x - (x^2 - n) / 2x.
The first test is a special case on zero; without it, the (n < 1) test causes an infinite loop. The next two tests normalize n to the range 1 < n <= 4; making the range smaller means that we can easily compute an initial approximation to the square root of n, which is done in the first computation of x, and then "unroll the loop" and iterate the recurrence equation a fixed number of times, thus eliminating the need for testing and recurring if the difference between two successive loops is too large.
By the way, Heron was a pretty interesting fellow. In addition to inventing a method for calculating square roots, he built a working jet engine, a coin-operated vending machine, and lots of other neat stuff!
You can read more about computing square roots at my blog.

it shouldnt have to be that complicated i wrote this up
def squareroot(n,x):
final = (0.5*(x+(n/x)))
print (final)
for i in range(0,10):
final = (0.5*(final+(n/final)))
print (final)
or you could change it to be like this
n = float(input('What number would you like to squareroot?'))
x = float(input('Estimate your answer'))
final = (0.5*(x+(n/x)))
print (final)
for i in range(0,10):
final = (0.5*(final+(n/final)))
print (final)

All you need to know is the nth term in the sequence. From the Leibniz series, we know this is ((-1)**n)/((2*n)+1). Just sum this series for all i with an initial condition of zero and you're set.
def myPi(n):
pi=0
for i in range(0,n):
pi=pi+((-1)**i)/((2*i)+1)
return 4*pi
print (myPi(10000))

Related

Create an algorithm whose recurrence is T(n) = T(n/3) + T(n/4) + O(n^2)

How do I go about problems like this one: T(n) = T(n/3) + T(n/4) + O(n^2)
I am able to use two for loops which will give me the O(n^2), right?
To interpret the equation, read it in English as: "the running time for an input of size n equals the running time for an input of size n/3, plus the running time for an input of size n/4, plus a time proportional to n^2".
Writing code that runs in time proportional to n^2 is possible using nested loops, for example, though it's simpler to write a single loop like for i in range(n ** 2): ....
Writing code that runs in time equal to the time it takes for the algorithm with an input of size n/3 or n/4 is even easier - just call the algorithm recursively with an input of that size. (Don't forget a base case for the recursion to terminate on.)
Putting it together, the code could look something like this:
def nonsense_algorithm(n):
if n <= 0:
print('base case')
else:
nonsense_algorithm(n // 3)
nonsense_algorithm(n // 4)
for i in range(n ** 2):
print('constant amount of text')
I've used integer division (rounding down) because I don't think it makes sense otherwise.
Here, we would use for and range(start, stop, steps), maybe with a simple to understand algorithm, similar to:
def algorithm_n2(n: int) -> int:
"""Returns an integer for a O(N2) addition algorithm
:n: must be a positive integer
"""
if n < 1:
return False
output = 0
for i in range(n):
for j in range(n):
output += n * 2
for i in range(0, n, 3):
output += n / 3
for i in range(0, n, 4):
output += n / 4
return int(output)
# Test
if __name__ == "__main__":
print(algorithm_n2(24))
Using print() inside a method is not a best practice.
Output
27748

Using recursion to calculate powers of large digit numbers

The goal is to calculate large digit numbers raised to other large digit numbers, e.g., 100 digit number raised to another 100 digit number, using recursion.
My plan was to recursively calculate exp/2, where exp is the exponent, and making an additional calculation depending on if exp is even or odd.
My current code is:
def power(y, x, n):
#Base Case
if x == 0:
return 1
#If d is even
if (x%2==0):
m = power(y, x//2, n)
#Print statment only used as check
print(x, m)
return m*m
#If d is odd
else:
m = y*power(y, x//2, n)
#Print statement only used as check
print(x, m)
return m*m
The problem I run into is that it makes one too many calculations, and I'm struggling to figure out how to fix it. For example, 2^3 returns 64, 2^4 returns 256, 2^5 returns 1024 and so on. It's calculating the m*m one too many times.
Note: this is part of solving modulus of large numbers. I'm strictly testing the exponent component of my code.
First of all there is a weird thing with your implementation: you use a parameter n that you never use, but simply keep passing and you never modify.
Secondly the second recursive call is incorrect:
else:
m = y*power(y, x//2, n)
#Print statement only used as check
print(x, m)
return m*m
If you do the math, you will see that you return: (y yx//2)2=y2*(x//2+1) (mind the // instead of /) which is thus one y too much. In order to do this correctly, you should thus rewrite it as:
else:
m = power(y, x//2, n)
#Print statement only used as check
print(x, m)
return y*m*m
(so removing the y* from the m part and add it to the return statement, such that it is not squared).
Doing this will make your implementation at least semantically sound. But it will not solve the performance/memory aspect.
Your comment makes it clear that you want to do a modulo on the result, so this is probably Project Euler?
The strategy is to make use of the fact that modulo is closed under multiplication. In other words the following holds:
(a b) mod c = ((a mod c) * (b mod c)) mod c
You can use this in your program to prevent generating huge numbers and thus work with small numbers that require little computational effort to run.
Another optimization is that you can simply use the square in your argument. So a faster implementation is something like:
def power(y, x, n):
if x == 0: #base case
return 1
elif (x%2==0): #x even
return power((y*y)%n,x//2,n)%n
else: #x odd
return (y*power((y*y)%n,x//2,n))%n
If we do a small test with this function, we see that the two results are identical for small numbers (where the pow() can be processed in reasonable time/memory): (12347**2742)%1009 returns 787L and power(12347,2742,1009) 787, so they generate the same result (of course this is no proof), that both are equivalent, it's just a short test that filters out obvious mistakes.
here is my approach accornding to the c version of this problem it works with both positives and negatives exposents:
def power(a,b):
"""this function will raise a to the power b but recursivelly"""
#first of all we need to verify the input
if isinstance(a,(int,float)) and isinstance(b,int):
if a==0:
#to gain time
return 0
if b==0:
return 1
if b >0:
if (b%2==0):
#this will reduce time by 2 when number are even and it just calculate the power of one part and then multiply
if b==2:
return a*a
else:
return power(power(a,b/2),2)
else:
#the main case when the number is odd
return a * power(a, b- 1)
elif not b >0:
#this is for negatives exposents
return 1./float(power(a,-b))
else:
raise TypeError('Argument must be interfer or float')

Finding the root of an equation with a constraint

In python, I would like to find the roots of equations of the form:
-x*log(x) + (1-x)*log(n) - (1-x)*log(1 - x) - k = 0
where n and k are parameters that will be specified.
An additional constraint on the roots is that x >= (1-x)/n. So just for what it's worth, I'll be filtering out roots that don't satisfy that.
My first attempt was to use scipy.optimize.fsolve (note that I'm just setting k and n to be 0 and 1 respectively):
def f(x):
return -x*log(x) + (1-x)*log(1) - (1-x)*log(1-x)
fsolve(f, 1)
Using math.log, I got value-errors because I was supplying bad input to log. Using numpy.log gave me some divide by zeros and invalid values in multiply.
I adjusted f as so, just to see what it would do:
def f(x):
if x <= 0:
return 1000
if x >= 1:
return 2000
return -x*log(x) + (1-x)*log(1) - (1-x)*log(1-x)
Now I get
/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py:221: RuntimeWarning: The iteration is not making good progress, as measured by the
improvement from the last ten iterations.
warnings.warn(msg, RuntimeWarning)
Using python, how can I solve for x for various n and k parameters in the original equation?
fsolve also allows guesses to be inserted for where to start. My suggestion would be to plot the equation and have the user type a initial guess either with the mouse or via text to use as an initial guess. You may also want to change the out of bounds values:
if x <= 0:
return 1000 + abs(x)
if x >= 1:
return 2000 + abs(x)
This way the function has a slope outside of the region of interest that will guide the solver back into the interesting region.

Trapezoid Rule in Python

I am trying to write a program using Python v. 2.7.5 that will compute the area under the curve y=sin(x) between x = 0 and x = pi. Perform this calculation varying the n divisions of the range of x between 1 and 10 inclusive and print the approximate value, the true value, and the percent error (in other words, increase the accuracy by increasing the number of trapezoids). Print all the values to three decimal places.
I am not sure what the code should look like. I was told that I should only have about 12 lines of code for these calculations to be done.
I am using Wing IDE.
This is what I have so far
# base_n = (b-a)/n
# h1 = a + ((n-1)/n)(b-a)
# h2 = a + (n/n)(b-a)
# Trap Area = (1/2)*base*(h1+h2)
# a = 0, b = pi
from math import pi, sin
def TrapArea(n):
for i in range(1, n):
deltax = (pi-0)/n
sum += (1.0/2.0)(((pi-0)/n)(sin((i-1)/n(pi-0))) + sin((i/n)(pi-0)))*deltax
return sum
for i in range(1, 11):
print TrapArea(i)
I am not sure if I am on the right track. I am getting an error that says "local variable 'sum' referenced before assignment. Any suggestions on how to improve my code?
Your original problem and problem with Shashank Gupta's answer was /n does integer division. You need to convert n to float first:
from math import pi, sin
def TrapArea(n):
sum = 0
for i in range(1, n):
deltax = (pi-0)/n
sum += (1.0/2.0)*(((pi-0)/float(n))*(sin((i-1)/float(n)*(pi-0))) + sin((i/float(n))*(pi-0)))*deltax
return sum
for i in range(1, 11):
print TrapArea(i)
Output:
0
0.785398163397
1.38175124526
1.47457409274
1.45836902046
1.42009115659
1.38070223089
1.34524797198
1.31450259385
1.28808354
Note that you can heavily simplify the sum += ... part.
First change all (pi-0) to pi:
sum += (1.0/2.0)*((pi/float(n))*(sin((i-1)/float(n)*pi)) + sin((i/float(n))*pi))*deltax
Then do pi/n wherever possible, which avoids needing to call float as pi is already a float:
sum += (1.0/2.0)*(pi/n * (sin((i-1) * pi/n)) + sin(i * pi/n))*deltax
Then change the (1.0/2.0) to 0.5 and remove some brackets:
sum += 0.5 * (pi/n * sin((i-1) * pi/n) + sin(i * pi/n)) * deltax
Much nicer, eh?
You have some indentation issues with your code but that could just be because of copy paste. Anyways adding a line sum = 0 at the beginning of your TrapArea function should solve your current error. But as #Blender pointed out in the comments, you have another issue, which is the lack of a multiplication operator (*) after your floating point division expression (1.0/2.0).
Remember that in Python expressions are not always evaluated as you would expect mathematically. Thus (a op b)(c) will not automatically multiply the result of a op b by c like you would expect with a mathematical expression. Instead this is the function call notation in Python.
Also remember that you must initialize all variables before using their values for assignment. Python has no default value for unnamed variables so when you reference the value of sum with sum += expr which is equivalent to sum = sum + expr you are trying to reference a name (sum) that is not binded to any object at all.
The following revision to your function should do the trick. Notice how I place multiplication operators (*) between every expression that you intend to multiply.
def TrapArea(n):
sum = 0
for i in range(1, n):
i = float(i)
deltax = (pi-0)/n
sum += (1.0/2.0)*(((pi-0)/n)*(sin((i-1)/n*(pi-0))) + sin((i/n)*(pi-0)))*deltax
return sum
EDIT: I also dealt with the float division issue by converting i to float(i) within every iteration of the loop. In Python 2.x, if you divide one integer type object with another integer type object, the expression evaluates to an integer regardless of the actual value.
A "nicer" way to do the trapezoid rule with equally-spaced points...
Let dx = pi/n be the width of the interval. Also, let f(i) be sin(i*dx) to shorten some expressions below. Then interval i (in range(1,n)) contributes:
dA = 0.5*dx*( f(i) + f(i-1) )
...to the sum (which is an area, so I'm using dA for "delta area"). Factoring out the 0.5*dx, makes the whole some look like:
A = 0.5*dx * ( (f(0) + f(1)) + (f(1) + f(2)) + .... + (f(n-1) + f(n)) )
Notice that there are two f(1) terms, two f(2) terms, on up to two f(n-1) terms. Combine those to get:
A = 0.5*dx * ( f(0) + 2*f(1) + 2*f(2) + ... + 2*f(n-1) + f(n) )
The 0.5 and 2 factors cancel except in the first and last terms:
A = 0.5*dx(f(0) + f(n)) + dx*(f(1) + f(2) + ... + f(n-1))
Finally, you can factor dx out entirely to do just one multiplication at the end. Converting back to sin() calls, then:
def TrapArea(n):
dx = pi/n
asum = 0.5*(sin(0) + sin(pi)) # this is 0 for this problem, but not others
for i in range(1, n-1):
asum += sin(i*dx)
return sum*dx
That changed "sum" to "asum", or maybe "area" would be better. That's mostly because sum() is a built-in function, which I'll use below the line.
Extra credit: The loop part of the sum can be done in one step with a generator expression and the sum builtin function:
def TrapArea2(n):
dx = pi/n
asum = 0.5*(sin(0) + sin(pi))
asum += sum(sin(i*dx) for i in range(1,n-1))
return asum*dx
Testing both of those:
>>> for n in [1, 10, 100, 1000, 10000]:
print n, TrapArea(n), TrapArea2(n)
1 1.92367069372e-16 1.92367069372e-16
10 1.88644298557 1.88644298557
100 1.99884870579 1.99884870579
1000 1.99998848548 1.99998848548
10000 1.99999988485 1.99999988485
That first line is a "numerical zero", since math.sin(math.pi) evaluates to about 1.2e-16 instead of exactly zero. Draw the single interval from 0 to pi and the endpoints are indeed both 0 (or nearly so.)

how to exit recursive math formula and still get an answer

i wrote this python code, which from wolfram alpha says that its supposed to return the factorial of any positive value (i probably messed up somewhere), integer or not:
from math import *
def double_factorial(n):
if int(n) == n:
n = int(n)
if [0,1].__contains__(n):
return 1
a = (n&1) + 2
b = 1
while a<=n:
b*=a
a+= 2
return float(b)
else:
return factorials(n/2) * 2**(n/2) *(pi/2)**(.25 *(-1+cos(n * pi)))
def factorials(n):
return pi**(.5 * sin(n*pi)**2) * 2**(-n + .25 * (-1 + cos(2*n*pi))) * double_factorial(2*n)
the problem is , say i input pi to 6 decimal places. 2*n will not become a float with 0 as its decimals any time soon, so the equation turns out to be
pi**(.5 * sin(n*pi)**2) * 2**(-n + .25 * (-1 + cos(2*n*pi))) * double_factorial(loop(loop(loop(...)))))
how would i stop the recursion and still get the answer?
ive had suggestions to add an index to the definitions or something, but the problem is, if the code stops when it reaches an index, there is still no answer to put back into the previous "nests" or whatever you call them
You defined f in terms of g and g in terms of f. But you don't just have a circular definition with no base point to start the recursion. You have something worse. The definition of f is actually the definition of g inverted. f is precisely undoing what g did and vice versa. If you're trying to implement gamma yourself (ie. not using the one that's already there in the libraries) then you need to use a formula that expresses gamma in terms of something else that you know how to evaluate. Just using one formula and its inversion like that is a method that will fail for almost any problem you apply it to.
In your code, you define double_factorial like
double_factorial(n) = factorial(n/2) * f(n) ... (1)
and in the factorial you define it as
factorial(n) = double_factorial(2*n) / f(2*n) ... (2)
which is equivalent to equation (1), so you created a circular reference without an exit point. Even math can't help. You have to define either factorial or double_factorial, e.g.
def factorials(n):
return tgamma(n + 1)

Categories

Resources