Calculating when the amount will be doubled using while loop - python

This is a simple exercise found in a book, which asks us to determine how long it takes for an amount to double at a given interest rate. My code is like this:
def main():
x = eval(raw_input("Initial Principal: "))
y = eval(raw_input("Interest rate: "))
count = 0
while x < 2*x:
x = x * (1 + y)
count = count + 1
print (x)
print (count)
main()
What it returns is:
Initial Principal: 1000
Interest rate: 0.5
inf
1734
What's wrong with my code?
Also I wonder if the above code would work if my amount and interest is small, e.g. amount = 1 and interest rate = 0.05, since there would include some floating point arithmetic I guess.
Thank you!

The culprit is the fact that you write:
while x < 2*x:
Since x > 0, that relation will always be False, you do not compare the new x with the old x, you compare the new x with twice the new x.
We can solve this effectively by using a variable x0 that store the initial amount:
def main():
x = x0 = eval(raw_input("Initial Principal: "))
y = eval(raw_input("Interest rate: "))
count = 0
while x < 2*x0:
x = x * (1 + y)
count = count + 1
print (x)
print (count)
main()
But there are still some problems with the code. For example you use eval. Do not use eval unless you absolutely have to: now a person can enter any type of Python code, also code that will break the system. Use float(..) instead to convert a string to an int:
def main():
x = x0 = float(raw_input("Initial Principal: "))
y = float(raw_input("Interest rate: "))
count = 0
while x < 2*x0:
x = x * (1 + y)
count = count + 1
print (x)
print (count)
main()
But now the code is still inefficient. There exists a fast way to calcuate the number of years using logarithms:
from math import log, ceil, pow
def main():
x = x0 = float(raw_input("Initial Principal: "))
y = float(raw_input("Interest rate: "))
count = ceil(log(2.0, y+1.0))
newx = x * pow(1.0+y, count)
print (newx)
print (count)

The problem is your while guard, which checks if the number is less than two times itself. To solve this, save the threshold you want to reach in a variable before the loop, and you have done:
threshold = 2 * x
count = 0
while x < threshold:
x = x * (1 + y)
count = count + 1

Related

I have a double while loop, and it does not seem to be working because of some logic I'm doing incorrectly

I have a double while loop, and it does not seem to be working because of some logic I'm doing incorrectly. I'm not sure what is wrong exactly, but I feel the code may be too complicated and somewhere, there is an error.
enter code here
import math
print("How many numbers am I estimating John?")
count = int(input("COUNT> "))
print("Input each number to estimate.")
better_guess = 0
initial_guess = 10
i = 0
j = 0
t = 1
list = []
for j in range(count):
num = float(input("NUMBER> "))
list.append(num)
j = j + 1
if j == count:
print("The square roots are as follows:")
while i <= len(list):
while t != 0 :
initial_guess = 10
better_guess = (initial_guess + (list[i])/initial_guess) / 2
if initial_guess == better_guess:
print(f"OUTPUT After {t} iterations, {list[i]}^0.5 = {better_guess}")
i = i + 1
break
initial_guess = better_guess
i = i + 1
There are some errors in your code, #x pie has pointed out some of them but not all. The most important is that you are need to initalize t for every number in the list, so you can get the iterations for the numbers separately. Also, t needs to be incremented in the while loop, not inside the if block.
You can also clean up the code considerably, for example the j variable is not being used, list comprehension can be used to shorten the code (pythonic way), and iterating over lists can be done with for num in list.
Putting this altogether produces this:
count = int(input('How many numbers am I estimating John? \nCOUNT> '))
print("Input each number to estimate.")
list = [float(input(f'NUMBER {i+1}> ')) for i in range(count)]
print("The square roots are as follows:")
for num in list:
initial_guess = 10
t = 0
while True:
better_guess = (initial_guess + num/initial_guess) / 2
t += 1
if initial_guess == better_guess:
print(f"OUTPUT After {t} iterations, {num}^0.5 = {better_guess}")
break
initial_guess = better_guess
Sample run:
How many numbers am I estimating John?
COUNT> 4
Input each number to estimate.
NUMBER 1> 1
NUMBER 2> 9
NUMBER 3> 16
NUMBER 4> 4
The square roots are as follows:
OUTPUT After 9 iterations, 1.0^0.5 = 1.0
OUTPUT After 7 iterations, 9.0^0.5 = 3.0
OUTPUT After 7 iterations, 16.0^0.5 = 4.0
OUTPUT After 8 iterations, 4.0^0.5 = 2.0
#viggnah is right, and I just ignored the num of iterations. But I think #viggnah 's num of iterations are 1 bigger than the actual num of iterations. E.g., if input is 4 and initial guess is 2, the iteration should be 0 rather than 1. Also I add except in case of illegal input.
I suppose the following code works as you expect.
import math
print("How many numbers am I estimating John?")
count = int(input("COUNT> "))
print("Input each number to estimate.")
better_guess = 0
initial_guess = 10
i = 0
j = 0
t = 1
list = []
while True:
try:
num = float(input("NUMBER> "))
list.append(num)
j = j + 1
if j == count:
print("The square roots are as follows:")
break
except:
print("Invalid input! Try again.")
while i < len(list):
initial_guess = 10
t = 0
while True:
better_guess = (initial_guess + (list[i])/initial_guess) / 2
if initial_guess == better_guess:
print(f"OUTPUT After {t} iterations, {list[i]}^0.5 = {better_guess}")
break
t = t + 1
initial_guess = better_guess
i = i + 1
You need to understand:
We only need initialize guess once for each number. So do it in the first while loop;
tneeds to be updated when initial_guess==better_guess rather than i, I believe this is a clerical error;
initial_guessneeds to be updated in the second loop;

I'm trying to do a function that does n+nn+nnn but it returns differently from what I expected. Can someone point out the flaw in my logic?

number = str(input('Please input a number: '))
def add_numbers(number):
sum = 0
for i in range (1,4):
number = number * i
sum += int(number)
return sum
print(add_numbers(number)
Output for range (1,2) in the loop = 5
Output for range(1,3) in the loop = 60
Output for range (1,4) in the loop = 555615
I tried it for cases where the loop iterates only once or twice which results in 5, and 5+55 = 60, respectively. But when I run it for 3 times it returns 555615. I'm guessing that it returns the correct sum which is 615 but is then added with the string 555 (which I don't understand why this does happen.
This should work:
number = str(input('Please input a number: '))
def add_numbers(number):
number = int(number)
sum = 0
for i in range(1,4):
number = number ** i
sum += int(number)
return sum
print(add_numbers(number))
Output:
Please input a number: 5
15655
Instead of number * i you need number to the power of i or number ** i. Also, since you are passing add_numbers a value from input(), number is a string and you need it to be an int which number = int(number) does.
If you want the equation to be n + nn + nnn instead of n * nn * nnn this works:
number = str(input('Please input a number: '))
def add_numbers(number):
number = int(number)
sum = 0
for i in range(1,4):
new = number ** i
sum += int(new)
return sum
print(add_numbers(number))
Output:
Please input a number: 5
155
This is because number is not reset back to 5 after each loop. (As per John Gordon's comment above).
With one small change, the answer you seek can be found.
number = input('Please input a number: ')
def add_numbers(number):
sum_ = 0
for i in range (1,4):
new = number * i
sum_ += int(new)
return sum_
print(add_numbers(number))
sum will be like that = number *1 + number *2 + number *3 ...
and u want = number + number * number + number * number * number
so u should do that :
sum += pow(number,i)

Finding probability from random number generator

I am working on a personal problem that requires me to find the probability that the sum of three randomly chosen real numbers between 0 and 1 is greater than 1. I have tried writing the code in python, but I think there's an error:
import random
a = random.random()
b = random.random()
c = random.random()
n = int(input("Enter a range: "))
for i in range(n):
wanted = 0
if (a + b + c > 1):
wanted += 1
else:
wanted += 0
print("The ratio is " + str(wanted/n))
Can you please point out the problems with my code or direct me otherwise?
To me seems like two issues :
each time you want to create a new set of random numbers, so they should go inside the loop
and wanted=0 should be before loop, you are resting it to 0 each time
import random
n = int(input("Enter a range: "))
wanted = 0
for _ in range(n):
a = random.random()
b = random.random()
c = random.random()
if a + b + c > 1:
wanted += 1
print(f"The ratio is {wanted/ n:.2%}")

Calculate and display the sum of the first 20 numbers in Fibonacci series

terms = int(input("Enter the terms: "))
x, y = 1, 2
count = 0
sum = 0.0
if terms <= 0:
print("Please enter a positive integer")
elif terms == 1:
print("Fibonacci sequence upto",terms,":")
print(x)
else:
print("Fibonacci sequence:")
while count < terms:
sum = z + x + y
print(x,end=" ")
z = x + y
x = y
y = z
count += 1
print("The sum of Fibonacci sequence:",sum)
'The error is the program cant defined the z and cant display the sum. Is that i put the sum code in wrong place?'
When you call
sum = z + x + y
you have not defined z.
Try this
x, y, z = 1, 2, 0
you are simply using z variable before even initializing it. The program doesn't know z exists and you are trying to use it to calculate sum.
first you need to initialize z and then use it to calculate sum.
You should replace "sum" with another name, try "summation"
Since you didn't defined z in first 14 lines, you can't use it in line 15. You should define z before using it.
Your sum calculation is not correct at all.

Program to find cuberoot of a number [duplicate]

This question already has answers here:
How to find cube root using Python? [duplicate]
(3 answers)
Closed 5 years ago.
So I'm a complete beginner (like less than a week) and wrote this code in python. It's supposed to find the cuberoot of a number if the solution is an integer, and approximate it otherwise. It does both instead of just one or the other. I've tried it multiple ways for hours now but it doesn't work. Any suggestions?
cube=int(input("what number's cube root do you want to find"))
epsilon = 0.01
increment = 0.0001
num_guesses = 0
for guess in range(cube+1):
if guess**3 == cube:
guess += 1
print (guess)
else:
guess1 = 0.0
while abs(guess1**3 - cube) >= epsilon:
guess1 += increment
num_guesses += 1
print('num_guesses =', num_guesses)
else:
print(guess1)
The problem is your indentation. Everything in your "else" statement needs to be indented to show that it is inside the "else" statement. You also have a few logical errors in your code. If you have found a number that, when cubed, is the desired number, you should print that number, not that number plus 1. And if you've found the solution, your program should stop there.
for guess in range(cube+1):
if guess**3 == cube:
print (guess)
return
guess1 = 0.0
Here is the working solution:
cube=int(input("what number's cube root do you want to find: "))
epsilon = 0.01
increment = 0.0001
num_guesses = 0
int_result_found = False
for guess in range(cube+1):
if guess**3 == cube:
print guess
int_result_found = True
break
if not int_result_found:
guess1 = 0.0
while abs(guess1**3 - cube) >= epsilon:
guess1 += increment
num_guesses += 1
#print 'num_guesses =', num_guesses
print(guess1)
As Erik said, there were some errors in your code. Key point is to stop after you've found integer solution, I've used boolean flag int_result_found for that.
One of the problems with you code is indenting. Python requires specific spacing in order to work properly.
The easiest way to avoid getting both answers is to create a boolean variable (I used "found_answer") to check if it is necessary to run the second code.
I've fixed you code, modifying it as little as possible:
cube=int(input("what number's cube root do you want to find"))
found_answer = False
for guess in range(cube+1):
if guess**3 == cube:
print ("integer answer:", guess)
found_answer = True
if found_answer == False:
epsilon = 0.01
increment = 0.0001
num_guesses = 0
guess1 = 0.0
while abs(guess1**3 - cube) >= epsilon:
guess1 += increment
num_guesses += 1
print('num_guesses =', num_guesses)
print("approximate answer:", guess1)
For your interest, here is a much more efficient solver:
# target function: y = x**3
def cube(x):
return x * x * x
def diff(f, epsilon = 0.001):
"""
Given function f, return a numeric approximation function for f'(x)
"""
def df(x):
return (f(x + epsilon) - f(x)) / epsilon
return df
def newton_solver(target_y, f, df = None, start_x = None, epsilon = 0.001, max_reps = 40):
"""
Newton Raphson approximation
Given real target_y and function f,
return real x such that f(x) = target_y +/- epsilon
"""
# if no differential function is provided, use a numeric approximation
if df is None:
df = diff(f)
# if no starting point is given, guess f(x) ='= x
if start_x is None:
x = target_y
else:
x = start_x
for _ in range(max_reps):
y = f(x)
err = y - target_y
if abs(err) < epsilon:
# close enough
return x
else:
# project the tangent to find a closer approximation
x -= err / (df(x) or epsilon)
# no answer found, bail out
raise ValueError("max_reps exceeded, no solution found")
def main():
y = int(input("What integer do you want to find the cube root of? "))
# find x such that y == x**3
approx_x = newton_solver(y, cube)
# round to the nearest integer
int_x = round(approx_x)
if cube(int_x) == y:
print("The exact cube root of {} is {}.".format(y, int_x))
else:
print("The cube root of {} is approximately {}.".format(y, approx_x))
if __name__ == "__main__":
main()
when it comes to "guess**3 == cube", I think you need to "break"
try this:
cube=int(input("what number's cube root do you want to find"))
epsilon = 0.01
increment = 0.0001
for i in range(cube + 1):
if i**3 == cube:
# break the loop
break
elif (i+1)**3 > cube > i**3: # this is to reduce unnecessary calculations
while (abs(i**3 - cube) >= epsilon):
i += increment
break
print(i)
and I'd like to make it a func:
cube=int(input("what number's cube root do you want to find"))
epsilon = 0.01
increment = 0.0001
def cuberoot(cube):
for i in range(cube + 1):
if i**3 == cube:
break
elif (i+1)**3 > cube > i**3:
while (abs(i**3 - cube) >= epsilon):
i += increment
break
return i
print(cuberoot(cube))
and what is more easy:
def cuberoot(cube):
return cube**(1/3)

Categories