3

This question/solution led me to another related question asked here - Help would be appreciated!

Updated current code below based on initial feedback

I am brand new to Python (this is my second program). I am currently using the Open Courseware from MIT to get an intro to CS using Python Academic Earth videos and I am working on Problem Set 1 Viewable Here. I have created this program that successfully recreates "Test Case 1" through the 12 months (excluding the "results" section...still working on that) but my question is, is the following (my) code as efficient as possible? I feel like I am repeating myself in it when it may not be necessary. :

Original Code:

balance = float(raw_input("Outstanding Balance: "))
interestRate = float(raw_input("Interest Rate: "))
minPayRate = float(raw_input("Minimum Monthly Payment Rate: "))
interestPaid = round((interestRate/12.0)*balance, 2)
minPayment = round(minPayRate*balance, 2)
principalPaid = round(minPayment-interestPaid, 2)
remainingBalance = round(balance-principalPaid, 2)
month = 1

while month < 12 :    
    if month > 1 :
        balance = remainingBalance
    interestPaid = round((interestRate/12.0)*balance, 2)
    minPayment = round(minPayRate*balance, 2)
    principalPaid = round(minPayment-interestPaid, 2)
    remainingBalance = round(balance-principalPaid , 2)   
    month = month+1

    print 'Month: ' + str(month)
    print 'Minimum monthly payment: ' + str(minPayment)
    print 'Principle paid: ' + str(principalPaid)
    print 'Remaining balance: ' + str(remainingBalance)

Current 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 you see anything else in this new code let me know!

Many thanks to those who helped me get it this far.

Community
  • 1
  • 1
tehaaron
  • 2,250
  • 10
  • 31
  • 54

4 Answers4

4

This is unrelated to any possible efficiency problems*, but you should look into the decimal module if you're doing financial arithmetic. Otherwise, you'll end up with strange rounding and representation errors.


*more precisely: It will reduce the efficiency but increase the correctness of your code.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
4
print "x: " + str(x)

Should be replaced by:

print "x:", x

This is a special case with print.


Change the looping to:

for month in xrange(1, 12+1):

Drop the check for the first loop and simply set balance to remainingBalance as the end.

Because you increment month manually, you print the wrong value each time.


If you mean efficiency as in execution efficiency, you're worrying about that too soon. If you mean it as in duplicating code, you do needlessly duplicate the math before the loop. Combined with the above:

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:', month
  print 'Minimum monthly payment:', minPayment
  print 'Principle paid:', principalPaid
  print 'Remaining balance:', remainingBalance

  balance = remainingBalance
Fred Nurk
  • 13,952
  • 4
  • 37
  • 63
  • Very helpful! I did notice that my calculations were a month off so I changed `if month > 1` to `if month >= 1` and it fixed it, but I MUCH prefer your method using `for` like Ignacio mentioned above. Also, my question about efficiency was in regards to extra, unnecessary (repeated) code. My original code didn't work when I tried to remove the math at the top, but now using the `for` loop it is possible. Thank you very much. Lastly, I originally used the `print "x:", x` code but I noticed it added an extra space for some reason. – tehaaron Feb 14 '11 at 09:35
  • maybe I was wrong, now nothing is changing after the first month. – tehaaron Feb 14 '11 at 09:46
  • @tehaaron: Sounds like you missed the line I added to the bottom of the loop body; it assigns to balance. – Fred Nurk Feb 14 '11 at 09:48
  • definitely a spelling error...took 10ish readovers sheesh. Thank you very much. – tehaaron Feb 14 '11 at 09:52
  • I added a follow-up question here: http://stackoverflow.com/questions/4997859/calculate-a-running-total-during-a-for-loop-python if you care to participate. Thanks again. – tehaaron Feb 14 '11 at 22:12
3

You should use string interpolation or formatting instead of passing to str() and adding.

print 'Month: %d' % (month,)
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Thank you, I made that change to my code. Is the method I used to make the calculations repeat done well/properly? – tehaaron Feb 14 '11 at 08:49
  • When i use `%f` to format the floats is there a way to limit the decimals to 2? – tehaaron Feb 14 '11 at 09:03
  • Absolutely. As given in the documentation, give the precision in the format specifier. `>>> '%.2f' % 123.456` `'123.46'` – Ignacio Vazquez-Abrams Feb 14 '11 at 09:07
  • Normally a `for` loop is used to loop a known number of times, but doing something on specific iterations can be tricky (but not really in this case). Also, see `enumerate()` for future reference. – Ignacio Vazquez-Abrams Feb 14 '11 at 09:08
  • Ah I asked that question too quickly. I looked it up and when I came back to delete/answer myself, you had beaten me to it! Thanks! (in reference to the decimal places) – tehaaron Feb 14 '11 at 09:10
  • Why iterpol with a one item tuple? not the item on its own. My tests show its much faster in time `C:\Users\Jakob>python -m timeit -c "'%s' % ('test',)" 10000000 loops, best of 3: 0.184 usec per loop` `C:\Users\Jakob>python -m timeit -c "'%s' % 'test'" 10000000 loops, best of 3: 0.0296 usec per loop` – Jakob Bowyer Feb 14 '11 at 13:17
1

For (speed) optimization in general you might want to read An Optimization Anecdote