MITx 6.00.1x Calculating Interest rate - python

So, I'm having a lot of trouble inputting my answer into the grader for the MIT Intro to CS in Python course on edX.
The specific problem ask for a program that will calculate the interest on a credit card given the monthly payment rate, interest rate, and initial balance.
I'm pretty sure my code is fine, I just can't get the grader to accept it.
I've tried changing the code to account for the names of the variables that the grader wants and removed the input prompts, function wrapper and return calls, but it still doesn't work.
Here is my initial code:
from math import *
b = float(input("balance = "))
r = float(input("annualInterestRate = "))
p = float(input("monthlyPaymentRate = "))
bval = []
def interest(b, r, p):
bal = (b - (b * p))
def update(bal, r):
balance = (bal + (r / 12.0) * bal)
return balance
if len(bval) < 12:
bval.append(update(bal, r))
return(interest(bval[-1], r, p))
elif len(bval) == 12:
return print("Remaning balance: " + "{:.2f}".format(bval[-1]))
interest(b, r, p)
And here is what it was modified to:
from math import *
bval = []
bal = (blance - (balance * monthlyPaymentRate))
def update(balance, annualInterestRate):
bal = round((balance + (annualInterestRate / 12.0) * balance), 2)
return bal
if len(bval) < 12:
bval.append(update(bal, annualInterestRate))
(interest(bval[-1], annualInterestRate, monthlyPaymentRate))
elif len(bval) == 12:
print("Remaning balance: " + "{:.2f}".format(bval[-1]))
Any help?

Related

Pycharm(specific?) 'int' object is not callable but code works

I'm currently working through hyperskill projects. The way I've done this code probably isn't ideal but i'm just trying to work in lists / classes / objects to stuff as I go.
On Pycharm it highlights all the self.methods under the if statement with " 'int' object is not callable " (or float) - but the code works as expected? Wondering why this would be.
Putting self.everything under the init with = None makes the highlighting / warning go away, but the code doesn't work.
This is also my first question, sorry if it is too broad. I tried looking for answers through other questions. Also not sure if I should be pasting all the code as I'm not sure which part is relevant.
from math import ceil, floor, pow, log
class LoanCalc:
options = ['Enter the loan principal:', 'Enter the monthly payment', 'Enter the loan interest:',
'Enter the number of periods:', 'Enter the annuity payment:']
def __init__(self):
pass
def loan_principle(self):
self.loan_principle = int(input(self.options[0]))
def monthly_payment(self):
self.monthly_payment = int(input(self.options[1]))
def loan_interest(self):
self.loan_interest = float(input(self.options[2]))
def i(self):
self.i = self.loan_interest / (12 * 100)
def periods(self):
self.periods = int(input(self.options[3]))
def a(self):
self.a = float(input(self.options[4]))
def main(self):
inp_options = input('''\
What do you want to calculate?
type "n" - for number of monthly payments,
type "a" for annuity monthly payment amount,
type "p" - for the monthly payment:
''')
if inp_options == 'n':
self.loan_principle()
self.monthly_payment()
self.loan_interest()
self. i()
n_months = log(self.monthly_payment /
(self.monthly_payment - self.i * self.loan_principle), 1 + self.i)
years = 0
if n_months < 11:
print(f'It will take {ceil(n_months)} months to repay this loan!')
elif n_months >= 12:
while n_months > 11:
n_months -= 12
years += 1
print(f'It will take {years} years and {ceil(n_months)} months to repay this loan!')
elif inp_options == 'p':
self.a()
self.periods()
self.loan_interest()
self. i()
loan_principal = self.a / ((self.i * ((1 + self.i) ** self.periods)) / (((1 + self.i) ** self.periods) - 1))
print(f'Your loan principal = {floor(loan_principal)}!')
elif inp_options == 'a':
self.loan_principle()
self.periods()
self.loan_interest()
self. i()
ann = ceil(self.loan_principle * ((self.i * pow(1 + self.i, self.periods)) /
(pow(1 + self.i, self.periods) - 1)))
print(f'Your monthly payment = {ann}!')
loan_calculator = LoanCalc()
loan_calculator.main()

Python Bisection Search

I'm new to Python, currently doing the MIT edX course. We had a problem to complete where we had to use the bisection method to find the lowest payment a person had to make to pay off a credit card dept in a year.We were given the balance and the annual interest rate. My code below works but it does not look correct to me. Does anyone have any insight in this? Thanks
def payment(balance, annualInterestRate):
newBalance = 0
monthlyInterest = annualInterestRate / 12
maxPaybal = (balance * (1 + monthlyInterest) ** 12) / 12
minPaybal = balance/12
while round(newBalance, 2) != 0.01 or round(newBalance, 2) != 0.00:
guess = (minPaybal + maxPaybal) / 2.0
newBalance = balance
months = 12
while months > 0:
prevBalance = newBalance - guess
uptdBalance = prevBalance + (prevBalance * monthlyInterest)
newBalance = uptdBalance
months -= 1
if round(newBalance, 2) == 0.01 or round(newBalance, 2) == 0.00:
return "Lowest Payment: ", round(guess, 2)
elif newBalance < 0.00:
maxPaybal = guess
else:
minPaybal = guess
print(payment(balance, annualInterestRate))

Regarding not changing value of N

The question is to find the fixed amount you need to pay to a credit card company when -
bal= the amount you need to pay at the beginning of 0th month
N = it is the monthly fixed amount to be to paid to the credit card company such that at the end of the year, you will have paid the total amount
int = interest rate of the credit card company
bal = int(raw_input("Enter balance"))
rate = int(raw_input("enter rate"))
lower_b = bal/12
upper_b = (bal + ((rate*bal)/1200))/12
N= (lower_b+upper_b)/2
def Credit(bal,rate,N):
global upper_b
global lower_b
i=1
k=bal
while (i<13):
print(N)
paid = N
bal = bal - paid
print("Balance remains to be paid is %s" %(round(bal,2)))
Interest = rate * bal /1200
print("The interest added on is %s" %(round(Interest,2)))
bal=bal+Interest
print ("The amount that needs to be payed is %s " %(round(bal,2)))
i=i+1
if bal==0:
return N
elif 50 < bal < 2000 :
lower_b = N
upper_b = upper_b
N = (upper_b +lower_b)/2
return Credit(k,rate,N)
elif -2000<bal< -50:
upper_b = N
lower_b = lower_b
N = (lower_b +upper_b)/2
return Credit(k,rate,N)
elif -50 < bal < 50:
return N
else:
return bal
result=Credit(bal,rate,N)
print(result)
My code never terminates. The problem is the value of N defined in the code is not changing. It remains fixed N = upper_b +lower_b)/2
Using recursion would not be the ideal approach, you also have logic errors including needing to get the interest rate for the month, your initial upper bound should be greater than the principal plus the interest. You can use a while loop with an inner for loop resetting the balance after each unsuccessful inner loop:
balance = int(raw_input("Enter balance"))
int_rate = float(raw_input("enter rate"))
int_rate /= 100
lower_b = balance / 12.
upper_b = ((balance * (1 + (int_rate / 12.0)) ** 12) / 12.0)
payment = (lower_b + upper_b) / 2
def Credit(bal, rate, low, high, pay):
new_b = bal
# calculate monthly interest rate
month_int = rate / 12
while abs(new_b) > 0.001: # use epsilon
# always reset balance
new_b = bal
for _ in range(12): # loop over 12 month range
new_b -= pay # deduct pay
new_b += month_int * new_b
# if we still have a balance we need to take more so set low to current payment
if new_b > 0:
low = pay
# else we took to much so set high to current payment
else:
high = pay
pay = (low + high) / 2.0
return "Lowest monthly payment over 12 months: {}".format(pay)
print(Credit(balance, int_rate, lower_b, upper_b, payment))

Return error in this "computepay" function

So I have this code that computes for your total money when you input hours and rate. Also if you work more than 40 hours you get 1.5 times rate per hours for each hour spent extra.
My question is I defined a function with this code:
and run it using computepay() the command prompt asks for
"Enter hours"
"Enter Rate"
Then it quits without spitting out the value that I want. I am complete noob with programming so please help and patience is appreciated.
Thank you.
def computepay():
try:
int1 = raw_input("Enter Hours")
h = float(int1)
int2= raw_input("Enter Rate")
r = float(int2)
except:
print "Error, please enter a numeric input"
quit()
if h >= 40:
pay1 = 40 * r + (h - 40) * r * 1.5
pay2 = h * r
return pay1
else:
return pay2
"Then it quits without spitting out the value that I want". Yes it does, but if you don't display it somewhere you won't see it. IOW you'd need:
def computepay():
# your code here
pay = computepay()
print "your pay is", pay
Now there's a mistake in your code:
if h >= 40:
pay1 = 40 * r + (h - 40) * r * 1.5
pay2 = h * r
return pay1
else:
return pay2
You define pay2 in the first part of the if branch but try to return it from the second - in which it doesn't exist. For any value of h < 40, this code will raise a NameError. What you want is:
if h >= 40:
pay1 = 40 * r + (h - 40) * r * 1.5
return pay1
else:
pay2 = h * r
return pay2
which could be simplified to:
if h >= 40:
return 40 * r + (h - 40) * r * 1.5
else:
return h * r
And also there's something wrong (wrt/ good coding practices) with your code: asking the values for the computation and doing the computation itself should not be mixed in the same function, as it doesn't make your function testable (automated unit tests) nor reusable (with a different user interface). The "right way" is to split your code to decouple the computation from the way it's called:
def computepay(h, r):
if h >= 40:
return 40 * r + (h - 40) * r * 1.5
else:
return h * r
def main():
try:
int1 = raw_input("Enter Hours")
h = float(int1)
int2= raw_input("Enter Rate")
r = float(int2)
# only catch the expected errors
except (ValueError, TypeError):
print "Error, please enter a numeric input"
quit()
print computepay(h, r)
if __name__ == "__main__":
main()
You are not assigning pay2 for else condition
if h >= 40:
pay1 = 40 * r + (h - 40) * r * 1.5
return pay1
else:
pay2 = h * r
return pay2
By the way you are doing you can call it as a function and print the functions return value
Without print you can not get the value so use print and pay2 should be calculated in else case
def computepay():
try:
int1 = raw_input("Enter Hours")
h = float(int1)
int2= raw_input("Enter Rate")
r = float(int2)
except:
print "Error, please enter a numeric input"
quit()
if h >= 40:
pay1 = 40 * r + (h - 40) * r * 1.5
return pay1
else:
pay2 = h * r
return pay2
print computepay()
or
def computepay():
try:
int1 = raw_input("Enter Hours")
h = float(int1)
int2= raw_input("Enter Rate")
r = float(int2)
except:
print "Error, please enter a numeric input"
quit()
if h >= 40:
pay1 = 40 * r + (h - 40) * r * 1.5
print pay1
else:
pay2 = h * r
print pay2
computepay()
It will work fine:
def computepay():
try:
int1 = raw_input("Enter Hours")
h = float(int1)
int2= raw_input("Enter Rate")
r = float(int2)
except:
print "Error, please enter a numeric input"
quit()
if h <= 40:
pay = h * r
else:
pay = 40 * r + (h - 40) * r * 1.5
return pay
print computepay()
Note: Don't forget to call computepay() with print statement to get the function's returned results to the output device i.e. to the consol.
Glad to have been of help! Feel free to accept my answer if you feel it was useful to you. :-)
After dealing the same issue, i suggest you to follow this code:
def computepay(hours,rate):
print ("In compute pay hours=", hours, " rate=", rate)
pay = rate * hours
if hours > 40:
pay = rate * (40) + rate * 1.5 * (h - 40)
return(pay)
hrs = input("Enter Hours:")
rate=input("Enter Rate:")
h = float(hrs)
r = float(rate)
p=computepay(h,r)
print('Pay: ', p)
## try & except:
try:
inp = h
hours = float(inp)
inp2 = r
rate = float(inp2)
except:
print ("Error, please enter numeric input")
quit()
def computepay():
try:
hours = raw_input("Enter hours:")
h = float(hours)
rate = raw_input("Enter rate:")
r = float(rate)
except:
print ("Error, enter numeric value please:")
quit()
if h >=40:
pays = 40 * r + (h - 40) * r * 1.5
return pays
else:
pays2 = h * r
return pays2
print (computepay())
This works 100%

Get my search to solve only if solution is negative (MIT6.00)

Folks,
I am getting my head stuck in knots here with problem 3 from PS1 in MIT6.00. I have written a couple of functions (one bisection search, and one function modelling the credit card debt). The problem is that it converges on a solution that gives a slightly positive remaining credit card balance. I could lower the tolerance in the bisection search, but I wanted to know if there was some more elegant way of making this optimiser return only negative results.
Cheers,
Aiden
code:
import numpy as np
def bisection(a, b, fun, tol, var = None):
"""Note that this only works if you put the independant variable
as the first argument in the parameter """
#def tstr(x):
# return 2*(x**2) - 3*x + 1
#sol = bisection(0,0.9,tstr,0.1)
c = (a+b)/2.0
if var != None:
arga = var[:]
argc = var[:]
arga.insert(0,a)
argc.insert(0,c)
else:
arga = a
argc = c
if (b-a)/2.0 <= tol:
#Debugging print statement 1:
#print 'SOL1: c = ', c
if var != None:
return [c] + fun(argc)
else:
return c
if fun(argc)[0] == 0:
if var != None:
return [c] + fun(argc)
else:
return c
elif fun(arga)[0]*fun(argc)[0] < 0:
b = c
else:
a = c
return bisection(a, b, fun, tol, var)
"""
Now we have defined a version of the paidOff function to work
with the bisection method"""
def paidOffBis(args):#(Pay, Bal, Apr):
"""Tester for Bisection Implementation"""
# TEST SIZE OF args:
if (type(args) != list)|(np.size(args) != 3):
print 'Incorrect size or type of input, input size:', np.size(args), '-', args
return None
Pay, Bal, Apr = args
Mpr = Apr/12.0
Baln = Bal
Nm = 0
for n in range(12):
Baln = Baln*(1 + Mpr) - Pay
if (Baln < 0)&(Nm == 0):
Nm = n + 1
if Baln < 0:
return [Baln, Nm]
else:
return [Baln, Nm]
Out_Bal = float(raw_input('Enter the outstanding balance on your credit card: '))
Apr = float(raw_input('Enter the annual credit card interest rate as a decimal: '))
varin = [Out_Bal, Apr]
#(Out_Bal*(1 + (Apr/12.0))**12.0)/12.0
sol = bisection(Out_Bal/12.0, Out_Bal, paidOffBis, 0.01, varin)
print 'RESULT'
print 'Monthly payment to pay off debt in 1 year: $%.2f' % sol[0]
print 'Number of months needed:', sol[2]
print 'Balance: $%.2f' % sol[1]
To ensure a balance less than or equal to zero you need to set your conditional statements correctly - you need to keep searching till that criteria is met. You asked for ... a more elegant way .... Using descriptive names for your variables and keeping it simple would certainly improve your code. Here is one way to craft a solution using a bisection search.
annualInterestRate = .1
balance = 1000
def balance_after_one_year(balance, annualInterestRate, payment):
'''Calculate the balance after one year of interest and payments.
balance --> int or float
annualInterestRate --> float between 0 and 1
payment --> float
returns float
'''
for _ in xrange(12):
balance = (balance - payment) * (1 + annualInterestRate / 12.0)
return balance
def min_payment(balance, annualInterestRate, tolerance = .01):
'''Find the minimum payment to pay off a loan.
Uses a bisection search.
Ensures balance is not positive.
balance --> float, int
annualInterestRate --> float less than one
tolerance --> float
'''
# we want the tolerance to be negative
# this isn't strictly a tolerance, it is a lower limit
tolerance = -abs(tolerance)
hi = balance
lo = 0
while True:
payment = (hi + lo) / 2.0
tmp_balance = balance_after_one_year(balance, annualInterestRate, payment)
if tmp_balance < tolerance:
hi = payment
# ensure balance is not positive
elif tmp_balance > 0:
lo = payment
else:
return payment, tmp_balance
Usage:
min_pmt, final_balance = min_payment(balance, annualInterestRate)
print 'minimum payment', min_pmt
print 'final balance', final_balance

Categories