Calculating time to earn a specific amount as interest - python-3.x

I cannot figure out the approach to this as the principle amount shall change after every year(if calculated annually, which shall be the easiest). Eventual goal is to calculate exact number of years, months and days to earn say 150000 as interest on a deposit of 1000000 at an interest rate of say 6.5%. I have tried but cannot seem to figure out how to increment the year/month/day in the loop. I don't mind if this is down voted because I have not posted any code(Well, they are wrong). This is not as simple as it might seem to beginners here.

It is a pure maths question. Compound interest is calculated as follows:
Ptotal = Pinitial*(1+rate/100)time
where Ptotal is the new total. rate is usually given in percentages so divide by 100; time is in years. You are interested in the difference, though, so use
interest = Pinitial*(1+rate/100)time – Pinitial
instead, which is in Python:
def compound_interest(P,rate,time):
interest = P*(1+rate/100)**time - P
return interest
A basic inversion of this to yield time, given P, r, and target instead, is
time = log((target+Pinitial)/Pinitial)/log(1+rate/100)
and this will immediately return the number of years. Converting the fraction to days is simple – an average year has 365.25 days – but for months you'll have to approximate.
At the bottom, the result is fed back into the standard compound interest formula to show it indeed returns the expected yield.
import math
def reverse_compound_interest(P,rate,target):
time = math.log((target+P)/P)/math.log(1+rate/100)
return time
timespan = reverse_compound_interest(2500000, 6.5, 400000)
print ('time in years',timespan)
years = math.floor(timespan)
months = math.floor(12*(timespan - years))
days = math.floor(365.25*(timespan - years - months/12))
print (years,'y',months,'m',days,'d')
print (compound_interest(2500000, 6.5, timespan))
will output
time in years 2.356815854829652
2 y 4 m 8 d
400000.0
Can we do better? Yes. datetime allows arbitrary numbers added to the current date, so assuming you start earning today (now), you can immediately get your date of $$$:
from datetime import datetime,timedelta
# ... original script here ...
timespan *= 31556926 # the number of seconds in a year
print ('time in seconds',timespan)
print (datetime.now() + timedelta(seconds=timespan))
which shows for me (your target date will differ):
time in years 2.356815854829652
time in seconds 74373863.52648607
2022-08-08 17:02:54.819492

You could do something like
def how_long_till_i_am_rich(investment, profit_goal, interest_rate):
profit = 0
days = 0
daily_interest = interest_rate / 100 / 365
while profit < profit_goal:
days += 1
profit += (investment + profit) * daily_interest
years = days // 365
months = days % 365 // 30
days = days - (months * 30) - (years * 365)
return years, months, days
years, months, days = how_long_till_i_am_rich(2500000, 400000, 8)
print(f"It would take {years} years, {months} months, and {days} days")
OUTPUT
It would take 1 years, 10 months, and 13 days

Related

Trying to show a full years amount based on a smaller fraction of the year's total

this is my first post.
Right now, I have a limited set of data ranging from the beginning of this financial year until now. I'm trying to show what a full year's worth of that data would look like.
For example, if the number is at 10, and the data range is from 1/07/2021 - 30/12/2021 (half the year), then the end output should be 20. Or for example, turn a 12 with 3/4 of the year date range to 16 for a full years' worth.
However, my current formula would end up with 15 (10 + "half") rather than (10 + 10)
Right now this is what I have, but I know there's something off on my logic, as the output is smaller than it should be:
D1+((364-(F1-E1))/365)*D1
where E1 is the start date and F1 is the end date, and d1 is the number for that date range
Thanks in advance
endDate - startDate will give you the number of days the data covers.
(endDate - startDate) / 365 will give you what fraction of a year the sample represents.
Let’s say this works out to be 30%, or 0.30.
annualValue * 0.30 = periodValue and therefore we know that periodValue / 0.30 = annualValue.
So there it is, the cell you want the Annual Value in should be:
= periodValue / ( ( endDate - startDate) / 365 )
I will leave it to you to replace each of the three named values in my example to be the correct cell references. I suspect that’s probably:
=D1/((F1-E1)/365) which is the same as (D1*365)/(F1-E1).
The easy way to remember this is that it’s just cross-multiplication.
periodValue / days is proportionate to annualValue / 365. Thus periodValue / days = annualValue / 365. Cross-multiply and you get periodValue * 365 = annualValue * days. Divide both sides by days and you get `annualValue = (periodValue * 365)/days.

how can I use the epoch

I need to print out “Your birthday is 31 March 2001 (a years, b days, c hours, d minutes and e seconds ago).”
I create input
birth_day = int(input("your birth day?"))
birth_month = int(input("your birth month?"))
birth_year = int(input("your birth year?"))
and I understand
print("your birthday is"+(birth_day)+(birth_month)+(birth_year)) to print out first sentence. but I faced problem with second one which is this part (a years, b days, c hours, d minutes and e seconds ago)
I guess I have to use “the epoch”
and use some of various just like below
year_sec=365*60*60*24
day_sec=60*60*24
hour_sec=60*60
min_sec=60
calculate how many seconds of the date since 1 January 1970 00:00:00 UTC:
import datetime, time
t = datetime.datetime(2001, 3, 31, 0, 0)
time.mktime(t.timetuple())
985960800.0
can anyone, could you solve my problem please?
Thank a lot
EDIT: See this answer in the thread kaya3 mentioned above for a more consistently reliable way of doing the same thing. I'm leaving my original answer below since it's useful to understand how to think about the problem, but just be aware that my answer below might mess up in tricky situations due to the quirks of the Gregorian calendar, in particular:
Every year that is exactly divisible by four is a leap year, except for years that are exactly divisible by 100, but these centurial years are leap years if they are exactly divisible by 400. For example, the years 1700, 1800, and 1900 are not leap years, but the years 1600 and 2000 are.
ORIGINAL ANSWER:
You can try using the time module:
import time
import datetime
def main(ask_for_hour_and_minute, convert_to_integers):
year, month, day, hour, minute = ask_for_birthday_info(ask_for_hour_and_minute)
calculate_time_since_birth(year, month, day, hour, minute, convert_to_integers)
def ask_for_birthday_info(ask_for_hour_and_minute):
birthday_year = int(input('What year were you born in?\n'))
birthday_month = int(input('What month were you born in?\n'))
birthday_day = int(input('What day were you born on?\n'))
if ask_for_hour_and_minute is True:
birthday_hour = int(input('What hour were you born?\n'))
birthday_minute = int(input('What minute were you born?\n'))
else:
birthday_hour = 0 # set to 0 as default
birthday_minute = 0 # set to 0 as default
return (birthday_year, birthday_month, birthday_day, birthday_hour, birthday_minute)
def calculate_time_since_birth(birthday_year, birthday_month, birthday_day, birthday_hour, birthday_minute, convert_to_integers):
year = 31557600 # seconds in a year
day = 86400 # seconds in a day
hour = 3600 # seconds in a hour
minute = 60 # seconds in a minute
# provide user info to datetime.datetime()
birthdate = datetime.datetime(birthday_year, birthday_month, birthday_day, birthday_hour, birthday_minute)
birthdate_tuple = time.mktime(birthdate.timetuple())
# figure out how many seconds ago birth was
seconds_since_birthday = time.time() - birthdate_tuple
# start calculations
years_ago = seconds_since_birthday // year
days_ago = seconds_since_birthday // day % 365
hours_ago = seconds_since_birthday // hour % 24
minutes_ago = seconds_since_birthday // minute % 60
seconds_ago = seconds_since_birthday % minute
# convert calculated values to integers if convert_to_integers is True
if convert_to_integers is True:
years_ago = int(years_ago)
days_ago = int(days_ago)
hours_ago = int(hours_ago)
minutes_ago = int(minutes_ago)
seconds_ago = int(seconds_ago)
# print calculations
print(f'Your birthday was {years_ago} years, {days_ago}, days, {hours_ago} hours, {minutes_ago} minutes, {seconds_ago} seconds ago.')
# to ask for just the year, month, and day
main(False, False)
# to ask for just the year, month, and day AND convert the answer to integer values
main(False, True)
# to ask for just the year, month, day, hour, and minute
main(True, False)
# to ask for just the year, month, day, hour, and minute AND convert the answer to integer values
main(True, True)
Tried to use descriptive variable names so the variables should make sense, but the operators might need some explaining:
10 // 3 # the // operator divides the numerator by the denominator and REMOVES the remainder, so answer is 3
10 % 3 # the % operator divides the numerator by the denominator and RETURNS the remainder, so the answer is 1
After understanding the operators, the rest of the code should make sense. For clarity, let's walk through it
Create birthdate by asking user for their information in the ask_for_birthday_info() function
Provide the information the user provided to the calculate_time_since_birth() function
Convert birthdate to a tuple and store it in birthdate_tuple
Figure out how many seconds have passed since the birthday and store it in seconds_since_birthday
Figure out how many years have passed since the birthday by dividing seconds_since_birthday by the number of seconds in a year
Figure out how many days have passed since the birthday by dividing seconds_since_birthday by the number of seconds in a day and keeping only the most recent 365 days (that's the % 365 in days_ago)
Figure out how many hours have passed since the birthday by dividing seconds_since_birthday by the number of seconds in a hour and keeping only the most recent 24 hours (that's the % 24 in hours_ago)
Figure out how many minutes have passed since the birthday by dividing seconds_since_birthday by the number of seconds in a minute and keeping only the most recent 60 minutes (that's the % 60 in minutes_ago)
Figure out how many seconds have passed since the birthday by dividing seconds_since_birthday and keeping only the most recent 60 seconds (that's the % 60 in seconds_ago)
Then, we just need to print the results:
print(f'Your birthday was {years_ago} years, {days_ago}, days, {hours_ago} hours, {minutes_ago} minutes, {seconds_ago} seconds ago.')
# if you're using a version of python before 3.6, use something like
print('Your birthday was ' + str(years_ago) + ' years, ' + str(days_ago) + ' days, ' + str(hours_ago) + ' hours, ' + str(minutes_ago) + ' minutes, ' + str(seconds_ago) + ' seconds ago.')
Finally, you can add some error checking to make sure that the user enters valid information, so that if they say they were born in month 15 or month -2, your program would tell the user they provided an invalid answer. For example, you could do something like this AFTER getting the birthday information from the user, but BEFORE calling the calculate_time_since_birth() function:
if not (1 <= month <= 12):
print('ERROR! You provided an invalid month!')
return
if not (1 <= day <= 31):
# note this isn't a robust check, if user provides February 30 or April 31, that should be an error - but this won't catch that
# you'll need to make it more robust to catch those errors
print('ERROR! You provided an invalid day!')
return
if not (0 <= hour <= 23):
print('ERROR! You provided an invalid hour!')
return
if not (0 <= minute <= 59):
print('ERROR! You provided an invalid minute!')
return
if not (0 <= second <= 59):
print('ERROR! You provided an invalid second!')
return

Working out number of years in compound interest using python function

School Question:
Build a function retirement_age(PMT, i, FV, start_age) that calculates the (whole) age at which your customer can retire, if they:
Invest an amount, PMT at the END of every YEAR (with the first
payment made exactly one year from now),
at an interest rate of i% per year, compounded annually.
They require an amount of AT LEAST FV in order to be able to afford
retirement.
They just turned start_age years old.
I am struggling to solve the number of years PMT would take to reach FV
This is my code:
def retirement_age(PMT, i, FV, start_age):
count = 0
while PMT <= FV: #PMT set to loop till it reaches FV
PMT = PMT * (1+i)
count = count + 1 #adds 1 to count value until while loop satisfied
age = count + start_age #adds count value to start_age to determine retirement age
return int(age) #returns age
print (retirement_age(20000, 0.1, 635339.63, 20))
my answer with this code:
57
The answer is supposed to be:
35
I can't tell what I'm doing wrong. And the task specifically mentions that we are not allowed to import external functions like math for example, which means I can't use math.log() which would probably solve all my problems.
First, I'll note that broad debugging questions like this aren't very appropriate for SO.
Having said that, I played around with it and after reading the specs again, I found the issue(s). I figured I might as well post it.
You only need to keep calculating while the principal is less than the future value. You can stop once they're equal.
The main issues however were that you aren't adding any money each year. You're just accumulating interest on the initial principal. And...
You invested PMT immediately. The investment doesn't happen until the end of the year, as the instructions emphasize. That means at the start of the looping, he has 0 invested. That means he doesn't start accumulating interest until the start of the second loop/year.
def retirement_age(PMT, i, FV, start_age):
age = start_age
p = 0
while p < FV:
p = PMT + p * (1+i)
age += 1
return int(age)
print(retirement_age(20000, 0.1, 635339.63, 20))
# 35
I introduced p to keep track of the running balance since it's separate from what's being added each year. Your logic for keeping track of age was also a little convoluted, so I simplified it down a bit.

Python Incorrect Values

I'm working on an assignment that implements while and for loops to calculate the cost of tuition each year for the next 5 years, when the initial amount is 8000 and increases 3% each year.
My program works, but I'm getting the wrong values when I actually calculate the projected tuition.
In
-------------------
tuition = 8000
increase = 0.03
tuition_total = 0
for year in range(0, 6):
tuition += ((tuition * increase) * year)
print(tuition, '\t', year)
Out
-------------------
8000.00 0
8240.00 1
8734.40 2
9520.49 3
10662.95 4
12262.39 5
According to the assignment written by my teacher, here are what the values are supposed to be:
In 1 year, the tuition will be 8240.00.
In 2 years, the tuition will be 8487.20.
In 3 years, the tuition will be 8741.82.
In 4 years, the tuition will be 9004.07.
In 5 years, the tuition will be 9274.19.
Are my operations off? Would appreciate any suggestions for what I should change. Thanks!
You are super close. Ask yourself, why you are multiplying (tuition * increase) by year?
The year that the tuition increase happens should be independent of the increase itself. Thus your for loop should be of the form:
for year in range(0, 6):
tuition += (tuition * increase)
print(tuition, '\t', year)
This should give you the same answers that your teacher provided as well.

Taking an input and rounding it up to the highest week.

new to Python or any programming languages, started learning a few weeks ago. Basically I need to figure out a code that will take a user input of number of days and translate it into weeks. Sounds easy enough, but say the user inputs 8 days, that would be considered two weeks. Any input must be rounded up to the nearest week.
So far I have
days = int(input("Please enter the number of days you will have the car: "))
weeks = (days/7)
but after that I am not sure how to make the code round the input up to the highest week.
Thanks for any help in advance!
Mezy
You should also use the modulus operator
weeks = (days // 7 ) + (1 if days % 7 != 0 else 0)

Resources