I am taking a course on edx and trying to solve a problem using bisection to calculate a monthly payment at which we can pay off the debt in a year. I have coded a solution but the results are a bit off than expected. Code is below. Answer code shared by edx is also listed beneath. Can you please share why my code is not giving same results? I am trying to get to to 2 decimal places accuracy.
balance=float(input('balance = '))
annualInterestRate=float(input('annualInterestRate = '))
remainingbalance=balance
low=float(remainingbalance/12)
high=float(remainingbalance*((1+(annualInterestRate/12))**12)/12.0)
if remainingbalance>0.01 or remaningbalance<0.01:
remainingbalance=balance
increment=round(float((high+low)/2), 2)
for i in range(1, 13):
unpaidbalance=remainingbalance-increment
interest=(annualInterestRate/12) * unpaidbalance
remainingbalance=round(unpaidbalance + interest, 2)
if remainingbalance>0.01:
low=increment
elif remainingbalance<-0.01:
high=increment
print('Lowest Payment: ', increment)
Sample code for solution provided by edx
init_balance = balance
monthlyInterestRate = annualInterestRate/12
lower = init_balance/12
upper = (init_balance * (1 + monthlyInterestRate)**12)/12.0
epsilon = 0.03
while abs(balance) > epsilon:
monthlyPaymentRate = (upper + lower)/2
balance = init_balance
for i in range(12):
balance = balance - monthlyPaymentRate + ((balance - monthlyPaymentRate) * monthlyInterestRate)
if balance > epsilon:
lower = monthlyPaymentRate
elif balance < -epsilon:
upper = monthlyPaymentRate
else:
break
print('Lowest Payment:', round(monthlyPaymentRate, 2))
My Code Results:
balance = 320000
annualInterestRate = 0.2
Lowest Payment: 29591.88
Edx Results:
balance = 320000
annualInterestRate = 0.2
Lowest Payment: 29157.09
Actually I am used to c++ and I am stuck in python. I can't seem to understand what's causing the infinite while loop.
The main goal of the code is to calculate how many months are required to save enough money for upfront payment.
#*******Initializing all the required variables***********
home_price = float(input("Enter the price of your dream home:")) # cost of the home
down_payment_portion = 0.25 # initial upfront pay for the home which is 25%
stamp_duty_portion = 0.03 # 3%
annual_salary = float(input("Enter your annual salary:"))
tax_portion = 0.2 # 20%
save_amount = 0
save_portion = float(input("Enter the amount of money you want to save after tax-cut:"))
annual_return = 0.05 # 5%
months = 0
#*********************************************************
#------------Calculating all the necessary values---------
down_payment_portion = down_payment_portion * home_price # calculating the down payment for the dream home
stamp_duty_portion = stamp_duty_portion * home_price # calculating the stamp duty for the home
tax_portion = tax_portion * annual_salary # calculating the tax cut
save_portion = save_portion * save_amount # calculating the portion of tax-cut income to be put into savings
annual_return = (save_amount * annual_return) / 12
upfront_payment = down_payment_portion + stamp_duty_portion
while(save_amount < upfront_payment):
save_amount = save_amount + annual_return
save_amount = save_amount + (annual_salary - tax_portion) * save_portion / 12
months = months + 1
print(f'You will need {months} month to save enough for your upfront payment{upfront_payment}.')
You initialise save_amount = 0
you get annual_return as annual_return = (save_amount * annual_return) / 12 which would be zero
you also get save_portion as save_portion = save_portion * save_amount which is again zero
Therefore your save_amount in the while loop is never incremented it too remains zero, save_amount < upfront_payment is always true ==> Infinite loop
In your code
while(save_amount < upfront_payment):
save_amount = save_amount + annual_return # 0 + 0 = 0
# 0 + (some value * 0)/12 = 0
save_amount = save_amount + (annual_salary - tax_portion) * save_portion / 12
Suppose you currently have $50,000 deposited into a bank account and the account pays you a constant interest rate of 3.5% per year on your deposit. You are planning to buy a house with the current price of $300,000. The price will increase by 1.5% per year. It still requires a minimum down payment of 20% of the house price.
Write a while loop to calculate how many (integer) years you need to wait until you can afford the down payment to buy the house.
m = 50000 #money you have
i = 0.035 #interest rate
h = 300000 #house price
f = 0.015 #amount house will increase by per year
d= 0.2 #percent of down payment on house
y = 0 #number of years
x = 0 #money for the down payment
mn = h*d #amount of down payment
while m <= mn:
m = (m+(m*i)) #money you have plus money you have times interest
y = y + 1 #year plus one
mn = mn +(h*f*y)
print(int(y))
The answer you should get is 10.
I keep getting the wrong answer, but I am not sure what is incorrect.
You can simplify the code by using the compound interest formula.
def compound_interest(amount, rate, years):
return amount * (rate + 1) ** years
while compound_interest(m, i, y) < d * compound_interest(h, f, y):
y += 1
If you are allowed to do without the while loop, you can resolve the inequality after the years y.
So you get this code snippet:
import math
base = (i + 1) / (f + 1)
arg = (d * h) / m
y = math.ceil(math.log(arg, base))
I'm pretty new to Python and I'm going through a starter book. The code isn't written in English so I tried my best to translate, hope you guys understand.
It has this exercise where we calculate the taxes from the user salary:
salary = float(input("Enter your salary to taxes calculation: "))
base = salary
taxes = 0
if base > 3000:
taxes = taxes + ((base - 3000) * 0.35)
base = 3000
if base > 1000:
taxes = taxes + ((base - 1000) * 0.20)
My problem is when the input is bigger than 3000, for example, if I run the code with the salary of 5000, the result will be 1100. But when I do the 'same' math on the calculator the result is 700, so I'm lost in here, could someone explain it please?
Please note that in case of salary 5000, the control will go to both the if statements. So it comes out as 700 from first, and 400 from second, therefore answer is 700+400. This also makes sense, as tax calculation is mostly partitioned in brackets, and is not a flat percentage on salary.
Alright, let's walk through it with your example of 5000
salary = float(input("Enter your salary to taxes calculation: "))
base = salary
# base = 5000
taxes = 0
if base > 3000: # base is larger than 3000, so we enter the if statement
taxes = taxes + ((base - 3000) * 0.35)
# taxes = 0 + ((5000 - 3000) * 0.35)
# taxes = 0 + 700
# taxes = 700
base = 3000 # base is set to 3000
if base > 1000: # base was set to 3000 in the line above, so we enter the if statement
taxes = taxes + ((base - 1000) * 0.20)
# taxes = 700 + ((3000 - 1000) * 0.20), remember taxes is already 700 from above
# taxes = 700 + 400
# taxes = 1100
since it is two if statements and not an if and an else we evaluate both statements when base is set larger than 3000. I hope that helps.
It flows on to the second function
so if I sub in the numbers:
Salary = 5000
base = 5000
taxes = 0
if 5000 > 3000:
taxes = 0 + ((5000- 3000) * 0.35) # = 700
base = 3000
if 3000 > 1000:
taxes = 700 + ((3000 - 1000) * 0.20) # = 1100
This is an economical equation which calculate tax for every part of salary.
the procedure would be this:
For amount greater than 3000 calculate 35% tax for this portion of salary.
For amount greater than 1000 (and less than 3000) calculate 20% tax for this portion of salary.
Tax over salary would be the summation of this taxes.
How to calculate the monthly fee on a loan?
Given is:
a: an amount to loan.
b: the loan period (number of months).
c: the interest rate p.a. (interests is calculated and added every month, 1/12 of the interest is added. So if the interest is on 12%, 1% interest is added every month).
d: the amount of money owed after the end of the period.
This problem is a bit different than the usual since, the goal is not to have the loan payed after the loan period has ended, but to still owe an amount that is given. I have been able to find an algorithm so solve the problem if I wanted to pay the entire amount, but it will of course not work for this problem where the goal is to end up owing a given amount rather than not owing anything.
I managed to make a solution to this problem by starting with an guess and then keep on improving that guess until it was close enough. I wondered however, if there is a better way to simply calculate this, rather than just guessing.
Edit: Here's how I'm doing it now.
def find_payment(start, end, months, interest):
difference = start
guess = int(start / months * interest)
while True:
total = start
for month in range(1, months + 1):
ascribe = total * interest / 12
total = total + ascribe - guess
difference = total - end
# See if the guess was good enough.
if abs(difference) > start * 0.001:
if difference < 0:
if abs(difference) < guess:
print "payment is %s" % guess
return evolution(start, guess, interest, months)
else:
mod = int(abs(difference) / start * guess)
if mod == 0:
mod = 1
guess -= mod
else:
mod = int(difference / start * guess)
if mod == 0:
mod = 1
guess += mod
else:
print "payment is %s" % guess
return evolution(start, guess, interest, months)
evolution is just a function that displays how the loan would look like payment for payment and interest for interest, summing up total amount of interest paid etc.
An example would be if I wanted to find out the monthly payments for a loan starting with $100k and ending at $50k with an interest of 8% and a duration of 70 months, calling
>>> find_payment(100000, 50000, 70, 0.08)
payment is 1363
In the above case I would end up owing 49935, and I went through the loop 5 times. The amount of times needed to go through the loop depends on how close I want to get to the amount and it varies a bit.
This is a basically a mortgage repayment calculation.
Assuming that start is greater than end, and that interest is between 0 and 1 (i.e. 0.1 for 10% interest)
First consider the part of the payment you want to pay off.
Principal = start - end
The monthly payment is given by:
pay_a = (interest / 12) / (1 - (1+interest/12) ^ (-months))) * Principal
You then need to consider the extra interest. Which is just equal to the remaining principal times the monthly interest
pay_b = interest / 12 * end
So the total payment is
payment = (interest / 12) * (1 / (1 - (1+interest/12) ^ (-months))) * Principal + end)
On the example you gave of
Start: 100000
End: 50000
Months: 70
Interest: 8%
pay_a = 896.20
pay_b = 333.33
Payment = 1229.54
When I tested these values in Excel, after 70 payments the remaing loan was 50,000. This is assuming you pay the interest on the notional before the payment is made each month.
Perhaps the easiest way to think about this is to split the loan in two parts, one part which is to be repaid in full and another part where you don't pay off anything. You have already computed the monthly fee for the first part.
You can keep paying the interest of every month; then, you will alway owe the same amont.
Owe_1 = a
Int_2 = Owe_1*(InterestRate/12)
Pay_2 = Int_2
Owe_2 = Owe_1 + Int_2 - Pay_2 # ==> Owe_1 + Int_2 - Int_2 = Owe_1
Int_3 = Owe_2*(InterestRate/12)
Pay_3 = Int_3
Owe_3 = Owe_2 + Int_3 - Pay_3 # ==> Owe_2 + Int_3 - Int_3 = Owe_2 = Owe_1
python code to calculate emi
class EMI_CALCULATOR(object):
# Data attributes
# Helps to calculate EMI
Loan_amount = None # assigning none values
Month_Payment = None # assigning none values
Interest_rate = None #assigning none values
Payment_period = None #assigning none values
def get_loan_amount(self):
#get the value of loan amount
self.Loan_amount = input("Enter The Loan amount(in rupees) :")
pass
def get_interest_rate(self):
# get the value of interest rate
self.Interest_rate = input("Enter The Interest rate(in percentage(%)) : ")
pass
def get_payment_period(self):
# get the payment period"
self.Payment_period = input("Enter The Payment period (in month): ")
pass
def calc_interest_rate(self):
# To calculate the interest rate"
self.get_interest_rate()
if self.Interest_rate > 1:
self.Interest_rate = (self.Interest_rate /100.0)
else:
print "You have not entered The interest rate correctly ,please try again "
pass
def calc_emi(self):
# To calculate the EMI"
try:
self.get_loan_amount() #input loan amount
self.get_payment_period() #input payment period
self.calc_interest_rate() #input interest rate and calculate the interest rate
except NameError:
print "You have not entered Loan amount (OR) payment period (OR) interest rate correctly,Please enter and try again. "
try:
self.Month_Payment = (self.Loan_amount*pow((self.Interest_rate/12)+1,
(self.Payment_period))*self.Interest_rate/12)/(pow(self.Interest_rate/12+1,
(self.Payment_period)) - 1)
except ZeroDivisionError:
print "ERROR!! ZERO DIVISION ERROR , Please enter The Interest rate correctly and Try again."
else:
print "Monthly Payment is : %r"%self.Month_Payment
pass
if __name__ == '__main__':# main method
Init = EMI_CALCULATOR() # creating instances
Init.calc_emi() #to calculate EMI
for more info visit : https://emilgeorgejames.wordpress.com/2015/07/29/python-emi-equated-monthly-installment-calculator/
This rather a detailed way but will give the whole payment as well
# Mortgage Loan that gives the balance and total payment per year
# Function that gives the monthly payment
def f1 (principle,annual_interest_rate,duration):
r = annual_interest_rate/1200
n = duration*12
a=principle*r*((1+r)**n)
b= (((1+r)**n)- 1)
if r > 0 :
MonthlyPayment = (a/b)
else :
MonthlyPayment = principle/n
return MonthlyPayment
# Function that gives the balance
def f2 (principle,annual_interest_rate,duration,number_of_payments):
r = annual_interest_rate/1200
n = duration*12
a= ((1+r)**n)
b= ((1+r)**number_of_payments)
c= (((1+r)**n)-1)
if r > 0 :
RemainingLoanBalance = principle*((a-b)/c)
else :
RemainingLoanBalance = principle*(1-(number_of_payments/n))
return RemainingLoanBalance
# Entering the required values
principle=float(input("Enter loan amount: "))
annual_interest_rate=float(input("Enter annual interest rate (percent): "))
duration=int(input("Enter loan duration in years: "))
# Output that returns all useful data needed
print ("LOAN AMOUNT:",principle,"INTEREST RATE (PERCENT):",annual_interest_rate)
print ("DURATION (YEARS):",duration,"MONTHLY PAYMENT:",int(f1(principle,annual_interest_rate,duration)))
k=duration+1
BALANCE=principle
total=0
for i in range (1,k):
TOTALPAYMENT= f1(BALANCE,annual_interest_rate,k-i)*12
total+= TOTALPAYMENT
BALANCE= f2(principle,annual_interest_rate,duration,12*i)
print("YEAR:",i,"BALANCE:",int(BALANCE),"TOTAL PAYMENT",int(total))
How about this?
def EMI_calc(principle, rate, time, frequency):
return (principle / ((1-((1+(rate/frequency))**(-1*(time*frequency))))/(rate/frequency)))
print("""
----- Welcome to EMI programe for Python -----
""")
print("\n You have chosen to know the EMI for Loan.\n")
input('\nTo Continue Press ENTER --- to ABORT Press ctrl+c > \n')
print("\nPlease Enter amount of Loan to be taken: >\n")
principle = int(input())
print("\nEnter rate of interst (%): >\n")
rate = float(input())/100
print("\nEnter Term (Years): >\n")
time = float(input())
print("\nPlease enter the frequency of installments) : >\n")
frequency = int(input())
EMI = round(EMI_calc(principle, rate, time, frequency),0)
print("""
---------------------------------------------------------------------
""")
print(f"""
The EMI for Loan of Rs.{principle};
at interest rate of {rate*100} % for {time} years;
would be: Rs.""", EMI)
print("""
---------------------------------------------------------------------
""")
Here is a code snippet using numpy functions. This shows you the payment, principal, interest, instalment and total_amount each month. Run it and see the output. You can also check the syntax for Excel "IPMT()" and "PPMT()" functions for more explanation of the arguments.
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.pmt.html#numpy.pmt
import math
import numpy as np
rate = 0.08
start_amount = 100000.0
end_amount = 50000.0
diff_amount = start_amount - end_amount
# nr_years = 4
payment_frequency = int (12)
nr_months = 70 # = nr_years * payment_frequency
per_np = np.arange (nr_months) + 1 # +1 because index starts with 1 here
pay_b = rate / payment_frequency * end_amount
ipmt_np = np.ipmt (rate / payment_frequency, per_np, nr_months, diff_amount) - pay_b
ppmt_np = np.ppmt (rate / payment_frequency, per_np, nr_months, diff_amount)
for payment in per_np:
idx = payment - 1
principal = math.fabs (ppmt_np [idx])
start_amount = start_amount - principal
interest = math.fabs (ipmt_np [idx])
instalment = principal + interest
print payment, "\t", principal, "\t", interest, "\t\t", instalment, "\t\t", start_amount
print np.sum (ipmt_np)