The problem is to write the python that calculates the interest due on a loan and prints a payment schedule. The interest due on a loan can be calculated according to the simple formula:
I = P × R × T
where I is the interest paid, P is the amount borrowed (principal), R is the interest rate, and T is the length of the loan.
Finally it needs to displayed as follows:
The program will print the amount borrowed, total interest paid, the amount of the monthly payment, and a payment schedule.
Sample session
Loan calculator
Amount borrowed: 100
Interest rate: 6
Term (years): 1
Amount borrowed: $100.00
Total interest paid: $6.00
Amount Remaining
Pymt# Paid Balance
----- ------- ---------
0 $ 0.00 $106.00
1 $ 8.84 $ 97.16
2 $ 8.84 $ 88.32
3 $ 8.84 $ 79.48
4 $ 8.84 $ 70.64
5 $ 8.84 $ 61.80
6 $ 8.开发者_JAVA技巧84 $ 52.96
7 $ 8.84 $ 44.12
8 $ 8.84 $ 35.28
9 $ 8.84 $ 26.44
10 $ 8.84 $ 17.60
11 $ 8.84 $ 8.76
12 $ 8.76 $ 0.00
The complete problem description is here: http://openbookproject.net/pybiblio/practice/wilson/loan.php To accomplish this I have written the code which is as follows:
import decimal
from decimal import *
class loan_calc:
def __init__(self):
decimal.getcontext().prec = 3
p = Decimal(input('Please enter your loan amount:'))
r = Decimal(input('Please enter the rate of interest:'))
t = Decimal(input('Please enter loan period:'))
r_e = r/100
i = p*r_e*t
term = t*12
r_a = p+i
amnt = p/term
count = 0
b_r = r_a
print "Payment\t\tAmount Paid\t\tBal.Rem."
while count <= term:
if count == 0:
print count,"\t\t"'0.00'"\t\t\t",b_r
count += 1
b_r -= amnt
continue
if term - count == 1:
amnt = b_r
print count,"\t\t",amnt,"\t\t\t",b_r
count += 1
b_r -= amnt
continue
else:
print count,"\t\t",amnt,"\t\t\t",b_r
b_r -= amnt
count += 1
continue
loan = loan_calc()
The use of Decimal(input())
is wrong:
>>> decimal.getcontext().prec=3
>>> decimal.Decimal(input('enter the number: '))
enter the number: 0.1
Decimal('0.1000000000000000055511151231257827021181583404541015625')
Using input
causes Python to evaluate the input, which creates a floating-point value. Fix this by using raw_input
and passing the string directly to Decimal
:
>>> decimal.Decimal(raw_input('enter the number: '))
enter the number: 0.1
Decimal('0.1')
Indent the code by 4 spaces, follow PEP 8, and avoid single-character variable names.
To start with, I recommend against doing both import decimal
and from decimal import *
. Pick one and use what you need from there. Generally, I do import whatever
and then use whatever.what_is_needed
to keep the namespace cleaner.
As commenters have already noted there's no need to create a class for something this simple (unless this is homework and your instructor requires it). Delete the class declaration, change your def __init__(self)
into a def main()
, and call main where you currently instantiate loan_class. For more about main functions, see Guido's classic post about them.
The input values should be checked. A simple way to do this would be with a try-except block as they are converted to Decimal. The code could look something like:
prin_str = raw_input('Please enter your loan amount: ')
try:
principal = decimal.Decimal(prin_str)
except decimal.InvalidOperation:
print "Encountered error parsing the loan amount you entered."
sys.exit(42)
To get this to work, you'd have to import sys
sometime before the sys.exit() call. I usually put my imports at the start of the file.
Since all your inputs are to be of the same type, you could easily make this a general use function and then call that function for each input.
There does appear to be some sort of bug in the calculations. Resolving that is left as an exercise for the reader. ;-)
Here's an answer closely patterned to the way yours is written. Using the method I explained and suggested when you asked about how to round off a floating number in python, it uses the decimal
module equivalent of the math
module's ceil
function to get the same answer as shown at the practice link (except for some minor output formatting). I also re-indented the code to the more commonly used 4-spaces, and renamed the variables to be a little more readable. Hope you learn something from it. Notice that I don't set decimal.getcontext().prec
to 3
(I don't believe it does what you think).
import decimal
def main():
principle = decimal.Decimal(raw_input('Please enter your loan amount:'))
rate = decimal.Decimal(raw_input('Please enter rate of interest (percent):')) / 100
term = decimal.Decimal(raw_input('Please enter loan period (years):')) * 12
interest = (principle * rate).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_HALF_EVEN)
balance = principle + interest
payment = (balance / term).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_CEILING)
print "Payment\t\tAmount Paid\t\tRem.Bal."
for count in range(1+term):
if count == 0:
print count, "\t\t0.00\t\t\t", balance
elif count == term: # last payment?
payment = balance
balance -= payment
print count, "\t\t", payment, "\t\t\t", balance
else:
balance -= payment
print count, "\t\t", payment, "\t\t\t", balance
main()
# > python loan_calc.py
# Please enter your loan amount:100
# Please enter rate of interest (percent):6
# Please enter loan period (years):1
# Payment Amount Paid Rem.Bal.
# 0 0.00 106.00
# 1 8.84 97.16
# 2 8.84 88.32
# 3 8.84 79.48
# 4 8.84 70.64
# 5 8.84 61.80
# 6 8.84 52.96
# 7 8.84 44.12
# 8 8.84 35.28
# 9 8.84 26.44
# 10 8.84 17.60
# 11 8.84 8.76
# 12 8.76 0.00
Rewritten (in Python 3, sorry). I'm not sure I understand the algorithm but you can modify it. Maybe this will help?
import decimal
balance = decimal.Decimal(input("Amount borrowed: "))
rate = decimal.Decimal(input("Rate (%): ")) / 100
term = int(input("Term (years): "))
print("\t".join(s.rjust(15) for s in ("Payment", "Amount Paid", "Balance")))
print("-"*54)
balance *= (1 + rate * term)
payment = balance / (12 * term)
total = 0
for month in range(12 * term):
if balance < payment:
payment = balance
print(("{: >15.2f}\t"*3)[:-1].format(payment, total, balance))
total += payment
balance -= payment
Notice the following:
- No silly variable name. Everything is named how it should be.
- String formatting to make the printing neater.
- No nasty
while
loop with multiple cases. You're going to print one line per month in the term, so use afor
loop.
The logic is much the same as previous answers, but severely reformatted. Enjoy!
# Loan payment calculator
import decimal
def dollarAmt(amt):
"Accept a decimal value and return it rounded to dollars and cents"
# Thanks to @Martineau!
# I found I had to use ROUND_UP to keep the final payment
# from exceeding the standard monthly payments.
return amt.quantize(decimal.Decimal('0.01'), rounding=decimal.ROUND_UP)
def getAmt(msg):
"Get user input and return a decimal value"
return decimal.Decimal(raw_input(msg))
class MonthlyFixedPaymentLoan(object):
def __init__(self, principal, yearlyRate, months):
self.principal = principal
self.yearlyRate = yearlyRate
self.months = months
self.interest = dollarAmt(principal * yearlyRate * (months/12))
self.balance = principal + self.interest
self.payment = dollarAmt(self.balance / months)
def __str__(self):
return ("Amount borrowed: ${0:>10}\n" +
"Total interest paid: ${1:>10}").format(dollarAmt(self.principal), dollarAmt(self.interest))
def payments(self):
# 'month 0'
yield 0, decimal.Decimal('0.00'), self.balance
pmt = self.payment
bal = self.balance
for mo in range(1,self.months):
bal -= pmt
yield mo, pmt, bal
# final payment
yield self.months, bal, decimal.Decimal('0.00')
def main():
amt = getAmt('Amount borrowed ($): ')
rate = getAmt('Interest rate (%/yr): ')
pd = getAmt('Loan term (years): ')
loan = MonthlyFixedPaymentLoan(amt, rate/100, pd*12)
print('')
print(loan)
print('')
print('Month Payment Balance')
print('----- -------- ----------')
for mo,pay,rem in loan.payments():
print('{0:>4} ${1:>7} ${2:>9}'.format(mo, pay, rem))
if __name__=="__main__":
main()
精彩评论