Logical thinking for a Calculation of Square root - python

I've been trying to decipher this problem for the last hour right now and having some trouble here. This is the problem
This method for calculating the square root of a number n starts by
making a (non zero) guess at the square root. It then uses the
original guess to calculate a new guess, according to the formula
newGuess = ((n / oldGuess) + oldGuess) / 2.0;
Have two variables oldGuess and newGuess. Initialize oldGuess to
n / 2.0 and calculate newGuess according to the above formula. Use
a while loop to iterate as long as the absolute value of the
difference between the oldGuess and newGuess is greater than
1.0E-06. Do not forget to reset the value of oldGuess to the
newGuess value in the while loop.
In your program you will prompt the user to enter a positive number.
If the number is negative, print an error message and ask the user to
try again. For a positive number, calculate the square root using the
above method. Find the difference between the square root you obtained
and the value obtained from using the exponentiation operator. Write
out the value the user entered, the square root you computed, and the
difference (your square root - n ** 0.5)
This is my program so far
def main():
n = eval(input("Enter a positive number: "))
while (n <= 0):
print ("Error please re-input")
n = eval(input("Enter a positive number: "))
oldGuess = n / 2.0
newGuess = ((n / oldGuess) + oldGuess) / 2.0;
difference = n - n ** 0.5
while (difference < 1 * 10 ** -6):
print ("Error")
difference = abs(n - n ** 0.5)
print ("Difference:", difference)
main()
So I don't really understand how we can tell the program to make a guess and then calculate the square root of variable n. I don't even think my while statements are right in this context. I don't use the already embedded function the squareroot built into python so it has to be done manually I believe still lost on what it means by the guess function.

while True:
n = float(input("Enter a positive number: "))
if n > 0:
break
print ("Error please re-input")
oldGuess = n / 2.0
while True:
newGuess = ((n / oldGuess) + oldGuess) / 2.0;
oldGuess = newGuess
if -1e-6 < n - newGuess * newGuess < 1e-6:
break
print ("Difference:", abs(n ** .5 - newGuess))

Change those eval()s to float()s. eval() executes any code it's handed, so that means your user could type something malicious there.
Now, use this for the second part:
oldGuess = n / 2.0
newGuess = ((n / oldGuess) + oldGuess) / 2.0
while (abs(oldGuess - newGuess) > 1e-06):
oldGuess, newGuess = newGuess, ((n / oldGuess) + oldGuess) / 2.0
print("Guess: " + str(n))
print("My root: " + str(newGuess))
print("Accuracy: " + str(newGuess - (n**0.5)))
That comma syntax is a Python idiom useful for swapping values without having to do:
temp = new
new = old * something
old = temp
Your condition for the while loop is looking to end looping when your difference is less than that (very small) value. So you will loop so long as it is greater than that.
Note: you can also use math.sqrt(n) instead of n ** 0.5. You'll have to import math.
If you want to see what your program is doing, try printing the values of oldGuess and newGuess within the while loop. You'll see it's changing them until you've arrived at your answer.
Edit:
I notice that you seem to be tripped up on why you have to do oldGuess = newGuess. Let me explain: the = operator is not the same as the equals sign in mathematics. The equals sign says that the thing on the left is the same thing as the thing on the right; i.e. they are equivalent. In Python, the = operator says "give the thing on the left the same value as the thing on the right." It is called the assignment operator. You are thinking of the == operator, which tests for equivalency (basically).
>>> a = 10
>>> b = 4
>>> b = a
>>> b
10
>>> a == b
True
>>> c = 6
>>> b = c
>>> b
6
>>> a == b
False
>>> b == c
True
>>> a == c
False
>>> a,b,c
(10, 6, 6)
As you can see, when you use the = operator, you don't "link" the variables together, saying that they are now the same thing. If you set b = a and then set b = c, b == a becomes false because b does not have the same value as a anymore. a does not change either, because b was assigned its value, not the other way around. Think of the = operator looking like <- instead (I think some languages actually use this as the assignment operator).
Why does this matter? Well, you do assign something new to a variable, you forget the old value. Unless you have another variable storing the same value, it's lost forever. Your assignment says to update the oldGuess to the previous newGuess. In other words, if your guesses were "a", "b", "c", "d", then you'd start with oldGuess as "a" and from there compute newGuess as "b". Since this would obviously not be the correct guess, you say the oldGuess is now what the newGuess just was - "b", and you compute the next newGuess, which is "c".
You need the value of oldGuess to compute the value of newGuess. But, you need the value of newGuess (before you changed it) to update the value of oldGuess. It's a catch-22, unless you store the previous value of newGuess as I showed above (as the swapping example). That is why you need this.

So I figured it out thanks guys for help. I didn't know we can't post homework questions on here but I am trying to definitely learn how to code so I can get better at it. Here was my final solution.
def main():
n = float(input("Enter a positive number: "))
while (n <= 0):
print ("Error please re-input")
n = eval(input("Enter a positive number: "))
oldGuess = n / 2.0
newGuess = 0
difference = 10
while (difference >= 1 * 10 ** -6):
newGuess = ((n / oldGuess) + oldGuess) / 2.0
difference = abs(newGuess - oldGuess)
oldGuess = newGuess
print ("Square Root is: ", newGuess)
differenceSqrt = newGuess - n ** 0.5
print ("Difference is: ", differenceSqrt)
main()
I still don't know how to use breaks effectively so thanks gnibbler but couldn't really follow your code too well. (New to this, sorry)

Related

How to define a variable by an equation containing it? (Python)

I´m solving a problem in which i have to print all the fibonacci numbers such that:
a <= f <= b
And i would like to start them by the smallest fibonacci number that is greater than or equal to a, in order to make my program run faster. For that, i need to define a variable "n", such that the nth Fibonacci number satisfies the condition above (smallest one that is greater than or equal to a). To define such variable, i need to find the smallest "n" that satisfies the fibonacci(n) general term equation.
I tried to find it by making a for loop, but it just ends up being as slow as if i started to check from the first Fibonacci Number. Anyone has any ideas on how to define it efficiently?
P.S. Here is my attempted code:
from math import sqrt, log, ceil
def Fibo(n):
if n == 1: return 1
elif n == 2: return 2
return Fibo(n-1) + Fibo(n-2)
while True:
try:
a, b = [int(i) for i in input().split()]
cont = 0
phi = (sqrt(5) + 1) / 2
i = ceil(log(a * sqrt(5), phi))
if Fibo(i-1) >= a: i -= 1
elif Fibo(n) < a: i += 1
while True:
if a <= Fibo(i) <= b: cont += 1
elif Fibo(i) > b:
break
i -= 1
print(cont)
except input() == "0 0":
break
Probably the most useful formula for your purpose for F(n), the nth Fibonacci number, is
from math import sqrt
phi = (sqrt(5) + 1) / 2 # the golden ratio
F(n) = round(phi**n / sqrt(5))
Therefore, one formula to get the value of n for a given value of a is
from math import sqrt, log, ceil
phi = (sqrt(5) + 1) / 2 # the golden ratio
n = ceil(log(a * sqrt(5), phi))
Due to approximation and rounding issues, you should check the values of n-1, n, and n+1 to ensure you got exactly the desired value. If you do this often, you should pre-define variables holding the value of the golden ratio and of the square root of five. If your value of a is too large for the float type to store it accurately, you would need a more complicated routine to handle the larger number.

How to avoid lists when analyzing order for palindromes?

Just want to apologize in advance for the general coding and logic gore you might encounter while reading this. I recently discovered Project Euler and thought it was fun. I've made it a point to not only find the answer, but make a generic function that could find the answer for any similar case given the appropriate input. For instance, problem number 4, involving palindromes, which can be seen here: https://projecteuler.net/problem=4
Essentially what I did was found a way to multiply every possible combination of numbers given a number of digits, n, then found products that were palindromes. However, anything above 3 digits just takes way too long to process. I believe this is because I used the list() function to take advantage of indexing to determine whether the product was a palindrome. Is there another way to do something of this nature? I feel like this is shoving a square through a circular hole.
Here's the function in question.
def palindrome(n):
number = 0
for i in range(0,n):
number = number + 9 * pow(10, i)
a = pow(10, n - 1) - 1
b = pow(10, n - 1)
while a * b < number * number:
a = a + 1
b = a
while b <= number:
c = a * b
b = b + 1
digits = list(str(int(c)))
lastdigits = digits[::-1]
numdigits = len(digits)
middle = int((numdigits - (numdigits % 2)) / 2) - 1
if numdigits > 1 and digits[:middle + 1] == lastdigits[:middle + 1] and digits[0] == digits[-1] == '9' and numdigits == 2 * n:
print(c)
"Find the largest palindrome made from the product of two 3-digit numbers."
3-digit numbers would be anything from 100 - 999. One thing about the largest product is guaranteed: The two operands must be as large as possible.
Thus, it would make sense to step through a loop starting from the largest number (999) to the smallest (100). We can append palindromes to a list and then later return the largest one.
When you calculate a product, convert it to a string using str(...). Now, checking for palindromes is easy thanks to python's string splicing. A string is a palindrome if string == string[::-1], where string[::-1] does nothing but return a reversed copy of the original.
Implementing these strategies, we have:
def getBiggestPalindrome():
max_palindrome = -1
for i in range(999, 99, -1):
for j in range(999, i - 1, -1):
prod = i * j
str_prod = str(prod)
if str_prod == str_prod[::-1] and prod > max_palindrome:
print(prod)
max_palindrome = prod
return max_palindrome
getBiggestPalindrome()
And, this returns
>>> getBiggestPalindrome()
906609
Note that you can use the range function to generate values from start, to end, with step. The iteration stops just before end, meaning the last value would be 100.

Python: Closest Power of Two To Target

I am attempting to find the closest power of two that is greater than or equal to a target value. A for loop must be used to achieve this. However, I am unsure of what to put as the range value so that upon reaching the required value the exponent will stop increasing by i and instead exit the for loop. Thanks for your help.
target = int(input("Enter target number: "))
def power_of_two(target):
x = 2
change = 0
power = 0
for i in range():
number = x ** change
change = i
if number >= target:
power = number
return power
p = power_of_two(target)
print("The closest power of 2 >= {0:d} is {1:d}." .format(target, p))
since you have to use for:
def power_of_two(target):
if target > 1:
for i in range(1, int(target)):
if (2 ** i >= target):
return 2 ** i
else:
return 1
that is assuming you want the value to be greater than or equal to 2^0
I have corrected your code, so that it works. I think you learn best from your mistakes :)
target = int(input("Enter target number: "))
def power_of_two(target):
x = 2
change = 0
power = 0
for i in range(target+1):
# target is okay for this, function terminates anyway
# add one to avoid error if target=0
number = x ** change
change = i
if number >= target: # you had indentation errors here and following
power = number
return power
p = power_of_two(target)
print("The closest power of 2 >= {0:d} is {1:d}." .format(target, p))
You could find a perfect value for the end of the range using logarithm with base 2, but then you wouldn't need the for loop anyway ;)
As a suggestion: maybe take a look at the binary representation of powers of 2. You could use a for loop with bitshifting for this.
EDIT: I had indentation errors myself, because of the weird formatting system here... maybe you haven't had these before :D

Why does recursive sequence not work correctly?

I'm totally new to Python and I'm trying to print the solution for a recursive sequence:
#Input sequence variables
a = float(raw_input("type in a = "))
n0 = int(raw_input("type in n_0 = "))
n1 = int(raw_input("type in n_1 = "))
y0 = float(raw_input("type in y_0 = "))
#Define function y_n (forward iteration)
def yn(n):
if (n==0):
return y0
else:
return (1/n)-a*yn(n-1)
#backward iteration
def yn_back(n):
return (1/a)*((1/n)-yn(n-1))
if(n1>=n0):
for i in range(n0,n1+1):
print(yn(i))
else:
for i in range(n0,n1+1):
print(yn_back(i))
But if I run this script with a=5, n0=1, n1=30 and y0=log(5/6)=0.182322 the solutions are very high (from 0.08839 to 3.29e+18) and the values are negative for even n. The solution is right for n=1. For other n, the (1/n) in the definition of yn(n) seems to be ignored.
Can someone help me?
Thanks a lot!
n is probably an integer, so 1/n is returning 0 for n greater than 1:
>>> 1/1
1
>>> 1/2
0
>>> 1.0/2
0.5
To make sure you're using float division, change 1 to 1.0 wherever you calculate 1/n:
(1.0/n)
Or convert n into a float.

About MIT 6.00 course lec06--Newton's method

I have tried to code in my own way, but found I got the wrong answer.
I have read this page. And try to start the process:
f(x)=x^2-e
The math:
So there is my code:
def sqrtRootNR(num, count, epsl):
"""
for test
"""
num = float(num)
guess = num / 2.0
diff = guess ** 2.0 - num
_cnt = 0
while abs(diff) > epsl and _cnt < count:
guess = guess - (guess ** 2.0 + epsl) / (guess * 2.0)
diff = guess ** 2.0 - num
_cnt = _cnt +1
print guess, _cnt
sqrtRootNR(2, 100, 0.0001)
However, I got the wrong answer.
The output of this function is:
D:\poc>python sq.py
0.0595177826557 100
One important skill in programming is knowing which information where will be most useful. If you add some simple debugging information:
while abs(diff) > epsl and _cnt < count:
guess = guess - (guess ** 2.0 + epsl) / (guess * 2.0)
diff = guess ** 2.0 - num
print guess, _cnt
_cnt = _cnt +1
print guess, _cnt
You can see that your program goes wrong quickly:
$ ./sqrt.py
0.49995 0
0.249874989999 1
0.124737394941 2
0.0619678553654 3
0.0301770577385 4
0.0134316410297 5
0.00299326718803 6
-0.0152075217183 7
-0.00431591416548 8
0.00942707405618 9
-0.000590335594744 10
....
It appears to halve the number every iteration until it goes negative, when the behavior gets very difficult to tell just at a glance. But you can obviously tell that the very first few iterations are wrong.
Something that looks quite fishy to me: (guess ** 2.0 + epsl)
You shouldn't actually use epsilon when evaluating Newton's method for square roots -- after all, you're trying to make sure your error is less than epsilon.
It looks like you are looking for zeroes of the function f = x^2+eps1. If eps1 is positive, there will be no real zeroes. This means that your program will oscillate around 0 forever after a certain point, as you saw. If you set eps1 to a negative value, I expect you would find a root.
Newton's method isn't bullet-proof, and there are cases where it can diverge.
Change (guess ** 2.0 + epsl) to (guess ** 2 - num) in your equation. You want to adjust your estimate every step by an amount proportional to your error, ie. your diff variable.
You also can use guess = 0.5 * (guess + num/guess)

Categories

Resources