MITx: 6.00.1x Introduction to Computer Science and Programming Using Python - python

So I'm very new to Python... The problem is as follows:
Write a program to calculate the credit card balance after one year if a person only pays the minimum monthly payment required by the credit card company each month.
My current code is as follows:
month = 1
minimumMonthlyPayment = (balance * monthlyPaymentRate)
totalPaid = 0.0
while month < 13:
print "Month: " + str(month)
print "Minimum Monthly Payment: " + str(round(minimumMonthlyPayment, 2))
balance = (balance - (balance * monthlyPaymentRate)) * (1 + (annualInterestRate/12))
minimumMonthlyPayment = (balance * monthlyPaymentRate)
print "Remaining Balance: " + str(round(balance, 2))
totalPaid += minimumMonthlyPayment
month += 1
print "Total Paid: " + str(round(totalPaid, 2))
print "Remaining Balance: " + str(round(balance, 2))
Here's the correct output:
So all the numbers are identical in both outputs but my Total Paid ends up being 1732.94 instead of the correct amount which is 1775.55. I added the numbers from my output up on a side calculator and it came out to 1775.55 as well. Is there something in my code that's borking this?
Here are the values for the variables that the test code uses:
balance = 4213;
annualInterestRate = 0.2;
monthlyPaymentRate = 0.04;

Great job! Your code is almost perfect. The only mistake is that line 8 needs to run before line 9. You're changing the balance and then using that changed balance to calculate the minimum monthly payment. You need to calculate the minimum monthly payment for each month before you update the balance.
Hope this helps!
balance = 4213
annualInterestRate = 0.2
monthlyPaymentRate = 0.04
totalPaid = 0.0
month = 1
minimumMonthlyPayment = balance * monthlyPaymentRate
while month < 13:
print "Month: " + str(month)
print "Minimum Monthly Payment: " + str(round(minimumMonthlyPayment, 2))
minimumMonthlyPayment = balance * monthlyPaymentRate
balance = (balance - (balance*monthlyPaymentRate))*(1+(annualInterestRate/12))
print "Remaining Balance: " + str(round(balance, 2))
totalPaid += minimumMonthlyPayment
month += 1
print "Total Paid: " + str(round(totalPaid, 2))
print "Remaining Balance: " + str(round(balance, 2))

You are recalculating your balance before calculating your minimumMonthlyPayment rate.
So balance * monthlyPaymentRate comes to a different amount on line 8 and 9 since balance has changed.
If you assign balance * monthlyPaymentRate to a variable before those lines and use it for both calculations it would correct this.

Related

Working on a problem to find the lowest number at which we can pay off debt in a year. Answer is a bit off

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

Calculate change from paid amount

Why is this code creating an infinite loop? I would think this should be an appropriate solution for this type of problem. For example, if the price was $5 and you paid $5.47, the program would print:
Quarters: 1
Dimes: 2
Nickels: 0
Pennies: 2
However, an infinite loop occurs and I'm not sure why. Anyone know the reason?
price = round(float(input("Enter the price: ")), 2)
print price
paid = round(float(input("Enter the amount paid: ")), 2)
print paid
change = round(float(paid - price), 2)
print change
quarters = 0
dimes = 0
nickels = 0
pennies = 0
while change > 0.00:
print change
if change >= .25:
change = change - .25
quarters += 1
continue
elif change >= .1:
change = change - .1
dimes += 1
continue
elif change >= .05:
change = change - .05
nickels += 1
elif change >= .01:
change = change - .01
pennies += 1
print "Quarters: " + str(quarters)
print "Dimes: " + str(dimes)
print "Nickels: " + str(nickels)
print "Pennies: " + str(pennies)
Rather than dealing with loops, I would suggest just subtracing off the change that you already gathered, prioritizing larger coins.
price = float(input("Enter the price: "))
paid = float(input("Enter the amount paid: "))
change = paid - price
if change < 0:
raise ValueError('Not enough paid')
quarters = change // 0.25
dimes = (change - (0.25 * quarters)) // 0.10
nickels = (change - (0.25 * quarters) - (0.10 * dimes)) // 0.05
pennies = 100 * (change - (0.25 * quarters) - (0.10 * dimes) - (0.05 * nickels))
print("Quarters: {:.0f}".format(quarters))
print("Dimes: {:.0f}".format(dimes))
print("Nickels: {:.0f}".format(nickels))
print("Pennies: {:.0f}".format(pennies))
There's one minor bug in the code which causes the program to only work correctly if price and amount paid are interchanged (e.g. price = 2, paid = 1). But that is not the issue causing the infinite loop.
Your code creates an infinite loop for e.g. the following arguments:
price: 5.6
paid: 5.4
The reason for the infinite loop can be seen from your own print output:
0.009999999999999275
0.009999999999999275
0.009999999999999275
0.009999999999999275
0.009999999999999275
0.009999999999999275
0.009999999999999275
...
Since change < 0.01, no if clause applies and thus the loop is never left.
How could you solve the problem more robustly?
Here's a sketch
from math import floor
change = paid - price
quarters = int(floor(change / 0.25))
change -= quarters * 0.25
dimes = int(floor(change / 0.1))
change -= dimes * 0.1
nickels = int(floor(change / 0.05))
change -= nickels * 0.05
pennies = int(floor(change / 0.01))
change -= pennies * 0.01
remaining = change
print("Quarters:", quarters)
print("Dimes:", dimes)
print("Nickels:", nickels)
print("Pennies:", pennies)
Personally I would also condense this into a loop over the coin type:
increments = {"quarter":0.25, "dimes": 0.1, "nickels": 0.05, "pennies": 0.01}
change_parts = {}
for inc_name, inc in increments.items():
amount = int(floor(change / inc))
print(inc_name, inc, amount)
change -= amount * inc
change_parts[inc_name] = amount
for inc_name, amount in change_parts.items():
print(inc_name + ":", amount)

Why is string not recognizing my output as an integer

balance = int(100)
balance *= 0.05 + balance
balance *= 0.05 + balance
balance *= 0.05 + balance
print (int(round ( balance, '.2f' )))
im trying to calculate what 100$ interest would be after 3 years compound interest.
I originally tried this
balance = 100
balance *= 0.05 + balance
balance *= 0.05 + balance
balance *= 0.05 + balance
print (format( balance, '.2f' ))
but my formatting caused the answer to be in the trillions instead of a 5 digit float.
You're multiplying the balances. Try this:
balance = int(100)
balance = balance * 0.05 + balance
balance = balance * 0.05 + balance
balance = balance * 0.05 + balance
print("{:.02f}".format(balance))
You have your operator precedence incorrect: the assignment operator is last. Thus, what you've done is
balance = balance * (0.05 + balance)
Instead, try one of the canonical ways to express interest:
rate = 0.05
balance += balance * rate
or
balance *= (1 + rate)
The parentheses aren't needed, but will help you read this.
Also, you might make a parameter (variable) for your repetition:
limit = 3
for year in range(limit):
balance *= 1 + rate
print("{:.02f}".format(balance))
You should pay attention to order of operations. balance *= 0.05 + balance will add 0.05 and balance before multiplying it to balance. What you'd want is balance = balance + balance * 0.05 or balance = balance * 1.05.
You can create a function to calculate compound interest to make it easier:
def comp_int(balance, rate, years):
return balance * (1 + rate)**years
balance = 100
rate = 0.05
years = 3
new_bal = comp_int(balance, rate, years)
print(f'{new_bal:.2f}')

add results of a for loop after each iteration in Python

I am starting to learn coding and beginning with Python. In my Python course I have a problem that is the following:
Write a program to calculate the credit card balance after one year if
a person only pays the minimum monthly payment required by the credit
card company each month.
The following variables contain values as described below:
balance - the outstanding balance on the credit card
annualInterestRate - annual interest rate as a decimal
monthlyPaymentRate - minimum monthly payment rate as a decimal
For each month, calculate statements on the monthly payment and
remaining balance, and print to screen something of the format:
Month: 1
Minimum monthly payment: 96.0
Remaining balance: 4784.0
(I've got that part alright)
Finally, print out the total amount paid that year and the remaining balance at the end of the year in the format:
Total paid: 96.0
Remaining balance: 4784.0
(It is the part of total paid that I can't resolve after many hours of trying and searching)
So here is what I need to do: add up together all the results of minimum monthly payment to get the total that was paid.
Here is my code:
def creditPayment(balance, annuelInterestRate, monthlyPaymentRate):
for month in range(1, 13):
monthlyInterestRate = annuelInterestRate/ 12.0
minimumMonthlyPayment = monthlyPaymentRate * balance
monthlyUnpaidBalance = balance - minimumMonthlyPayment
balance = monthlyUnpaidBalance + (monthlyInterestRate * monthlyUnpaidBalance)
totalPaid = sum((minimumMonthlyPayment) for _ in range(0, 13))
print 'Month: ', month
print 'Minimum monthly payment: ', round(minimumMonthlyPayment, 2)
print 'Remaining balance: ', round(balance, 2)
print ' '
print 'Total paid: ', round(totalPaid, 2)
print 'Remaining balance: ', round(balance, 2)
print creditPayment(4213, 0.2, 0.04)
Everything works fine except for the total paid that adds up 12 times only the first value of minimumMonthlyPayment. I can't make it better.
If I've correctly interpreted your question, I'm assuming that your intent is to increment totalPaid by the minimumMonthlyPayment for each month. If so:
totalPaid = 0.0
for month in range(1, 13):
#
# Other stuff you're doing in the loop
#
totalPaid += minimumMonthlyPayment
Each time through the loop, totalPaid gets incremented by the minimum payment computed for that particular month. This logic of course has to be changed/augmented if you intend to add cases in which anything other than the minimum payment is paid.
In your for loop, you have:
totalPaid = sum((minimumMonthlyPayment) for _ in range(0, 13))
This is setting totalPaid to be 13 times the minimumMonthlyPayment, as it is for that iteration of the loop, so on the last loop the value is set to 13 times the last minimum payment. You need to add one value to the totalPaid each iteration, so that the value is updated before it is added. Here is what I would change the code to:
def creditPayment(balance, annuelInterestRate, monthlyPaymentRate):
totalPaid = 0
for month in range(1, 13):
monthlyInterestRate = annuelInterestRate/ 12.0
minimumMonthlyPayment = monthlyPaymentRate * balance
monthlyUnpaidBalance = balance - minimumMonthlyPayment
balance = monthlyUnpaidBalance + (monthlyInterestRate * monthlyUnpaidBalance)
totalPaid +=minimumMonthlyPayment
print 'Month: ', month
print 'Minimum monthly payment: ', round(minimumMonthlyPayment, 2)
print 'Remaining balance: ', round(balance, 2)
print ' '
print 'Total paid: ', round(totalPaid, 2)
print 'Remaining balance: ', round(balance, 2)
print creditPayment(4213, 0.2, 0.04)
print creditPayment(4213, 0.2, 0.04)
Also, since you aren't using the actual value of your iterator in for _ in range(0, 13), it would be more readable to just use range(13). I suspect you may have meant to have it loop 12 times, since the rest of your program does.

Calculate a running total during a for loop - Python

Edit: Below is my working code based on the feedback/answers I recieved.
This question stems from my previous question that came up while learning Python/CS using open courseware from MIT. --See my previous question here--
I am using the following code to make a list of month payments and other things. However at the end of the loop I need to give a running total for the total amount that has been paid of the months.
Original Code
balance = float(raw_input("Outstanding Balance: "))
interestRate = float(raw_input("Interest Rate: "))
minPayRate = float(raw_input("Minimum Monthly Payment Rate: "))
for month in xrange(1, 12+1):
interestPaid = round(interestRate / 12.0 * balance, 2)
minPayment = round(minPayRate * balance, 2)
principalPaid = round(minPayment - interestPaid, 2)
remainingBalance = round(balance - principalPaid, 2)
print 'Month: %d' % (month,)
print 'Minimum monthly payment: %.2f' % (minPayment,)
print 'Principle paid: %.2f' % (principalPaid,)
print 'Remaining balance: %.2f' % (remainingBalance,)
balance = remainingBalance
if month in xrange(12, 12+1):
print 'RESULTS'
print 'Total amount paid: '
print 'Remaining balance: %.2f' % (remainingBalance,)
The problem is that I have not been able to figure out how to keep a running total of the amounts paid. I tried adding totalPaid = round(interestPaid + principalPaid, 2) but that just led to a total for a single month, I cant seem to get it to keep that value for each month and then add them all up at the end to be printed out.
Also I know that the resulting amount should be 1131.12
I have found many examples of doing this when each value is know, via a list, but I cant seem to extrapolate that correctly.
Fixed Code
balance = float(raw_input("Outstanding Balance: "))
interestRate = float(raw_input("Interest Rate: "))
minPayRate = float(raw_input("Minimum Monthly Payment Rate: "))
totalPaid = 0
for month in xrange(1, 12+1):
interestPaid = round(interestRate / 12.0 * balance, 2)
minPayment = round(minPayRate * balance, 2)
principalPaid = round(minPayment - interestPaid, 2)
remainingBalance = round(balance - principalPaid, 2)
totalPaid += round(minPayment, 2)
print 'Month: %d' % (month,)
print 'Minimum monthly payment: %.2f' % (minPayment,)
print 'Principle paid: %.2f' % (principalPaid,)
print 'Remaining balance: %.2f' % (remainingBalance,)
balance = remainingBalance
if month in xrange(12, 12+1):
print 'RESULTS'
print 'Total amount paid: %.2f' % (totalPaid,)
print 'Remaining balance: %.2f' % (remainingBalance,)
Before your loop, initialize a variable to accumulate value:
total_paid = 0
And then, in the body of your loop, add the appropriate amount to it. You can use the += operator to add to an existing variable, e.g.
total_paid += 1
is a short form for total_paid = total_paid + 1. You don't want to give total_paid a new value each iteration, rather you want to add to its existing value.
I'm not sure about the specifics of your problem, but this is the general form for accumulating a value as you loop.
You always make the minimum payment? Just use minPayment instead of figuring out that math again. Keep a running total, then print it out after the loop.
balance = float(raw_input("Outstanding Balance: "))
interestRate = float(raw_input("Interest Rate: "))
minPayRate = float(raw_input("Minimum Monthly Payment Rate: "))
paid = 0
for month in xrange(1, 12+1):
interestPaid = round(interestRate / 12.0 * balance, 2)
minPayment = round(minPayRate * balance, 2)
principalPaid = round(minPayment - interestPaid, 2)
remainingBalance = round(balance - principalPaid, 2)
paid += minPayment
print # Make the output easier to read.
print 'Month: %d' % (month,)
print 'Minimum monthly payment: %.2f' % (minPayment,)
print 'Principle paid: %.2f' % (principalPaid,)
print 'Remaining balance: %.2f' % (remainingBalance,)
balance = remainingBalance
print
print 'RESULTS'
print 'Total amount paid:', paid
print 'Remaining balance: %.2f' % (remainingBalance,)
Also notice that range has exactly one value, so you'd just check month == 12, but it's simply not necessary here.
This answer worked for me:
First, create the derived value:
df.loc[0, 'C'] = df.loc[0, 'D']
Then iterate through the remaining rows and fill the calculated values:
for i in range(1, len(df)):
df.loc[i, 'C'] = df.loc[i-1, 'C'] * df.loc[i, 'A'] + df.loc[i, 'B']
Index_Date
A
B
C
D
2015/01/31
10
10
10
10
2015/02/01
2
3
23
22
2015/02/02
10
60
290
280
You actually have to initialize totalPaid to 0 and then
totalPaid = round(interestPaid + principalPaid, 2) + totalPaid
Inside the loop. Your problem is that you're not accumulating the total, you're just setting a new one on each iteration.
sounds like you were close. The problem is that you were overwriting the total each time. Try something like this:
totalPaid = totalPaid + round(interestPaid + principalPaid, 2)

Categories

Resources