Announcement

Collapse
No announcement yet.

?Rounding errors?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Mel Bishop
    replied
    Originally posted by Paul Dixon:
    the problem is the line...
    Okay, let me do some razzle-dazzle and see what I come up with.
    I'll let you know. Thanks.


    ------------------

    Leave a comment:


  • Paul Dixon
    replied
    Mel,
    the problem is the line :

    payment = int(te * 100 + .5) / 100


    te is calculated as $454.2312

    The above line makes this int(45423.62)/100 = $454.23

    This is less than the 454.2312 needed to repay the loan on time so there is a shortfall of $0.0012 per month. This accumulates to give the 361st payment.

    You need to change the above line so that the repayment is ALWAYS higher (rounded up to the nearest cent) than the exact figure required to pay off the loan on time.
    What you're doing is rounding to the nearest cent even if that means rounding down.. which will then leave a shortfall.

    Paul.


    ------------------

    Leave a comment:


  • Mel Bishop
    replied
    I'm not refusing to post my code. I simply would prefer not to
    if I don't have to. Here is what I have so far. The program
    isn't finished. I would like to find out where the rounding
    errors are before I go on to future things.
    Code:
    	$lib all off
    	color 14,1
    
            do
            cls
            f$ = "$###,###.##"
    
            locate  5,29 : Print;"Regular payment on a loan"
    
    	locate  7,25 : Input;"Term in years: ",years
            if years = 0 then exit loop
    
            locate  9,25 : Input;"    Principal: ",principal
            if principal = 0 then exit loop
    
            save = principal
            locate 11,25 : Input;"Interest rate: ",interest
            if interest = 0 then exit loop
            monthly = 12				'Monthly payments
    
    REM	Computer monthly payments
            te = ((interest / 100) * principal / monthly) / _
                 (1-1 / ((interest / 100) / monthly + 1) ^ (monthly * years))
    
            payment = int(te * 100 + .5) / 100
    
    
    [b]
    REM     This is the mod that I came up with in response to Pauls
    REM     response. It seems to work in as far as making the 
    REM     months come out exact.
    
            te$ = str$(te)
            p = instr(te$,".")
            if p = 0 then te$ = te$ + ".000"
    
            te = val(mid$(te$,p+3,1))
            if te < 5 then payment = payment + .01
    [/b]
    rem
            t$ = using$(f$,payment)
            t$ = remove$(t$," ")
            locate 15,22 : print;"Regular payments: ";t$
    
            locate 17,10
            print;"Press ESCape to end the program or any other key to"
            locate 18,10
            print;"write the data to a disk file."
    
            if abort = 0 then
    
            fi$ = "amort.txt"
            te$ = dir$(fi$)
            if te$ <> "" then kill fi$
    
            open fi$ for binary as #1
            crlf$ = chr$(13) + chr$(10)
            separator$ = string$(75,"-") + crlf$
    
            m$ = "Original loan amount: " + using$(f$,principal) + crlf$
       m$ = m$ + "      Length of loan: " + Str$(years) + " Years" + crlf$
       m$ = m$ + "       Interest Rate: " + str$(interest) + " Percent" + crlf$
       m$ = m$ + crlf$
       m$ = m$ + "     Monthly Payment: " + using$(f$,payment)
       m$ = m$ + crlf$ + crlf$
    
    	put$ #1,m$
    	put$ #1,separator$
    	put$ #1,"Month"      + space$(5)
    	put$ #1,"Interest"   + space$(5)
    	put$ #1,"Principal"  + space$(8)
    	put$ #1,"Balance"    + space$(7)
    	put$ #1,"Equity"     + space$(5)
            put$ #1,"Accr Inter" + crlf$
    
    	put$ #1,separator$
    
            for month = 1 to monthly * years + 5
    
    REM	Calculate interest paid with each payment
    	tointerest = int((principal * (interest / 100) / monthly) * 100 + .5) / 100
    
    REM	Add up the accumulated interest
    	accum = accum + tointerest
    
    REM     How much of the payment goes to principal
            toprincipl = payment - tointerest
    
    REM     How much equity is built up
    	equity = equity + toprincipl
            if equity > save then equity = save
    
    REM     How much of the principal is left
            principal  = principal - toprincipl
    
    REM	Zero out a negative number
            if principal < 0 then principal = 0
    
            t1$ = using$(f$,tointerest) : t1$ = remove$(t1$," ")
            t2$ = using$(f$,toprincipl) : t2$ = remove$(t2$," ")
            t3$ = using$(f$,principal)  : t3$ = remove$(t3$," ")
            t4$ = using$(f$,equity)     : t4$ = remove$(t4$," ")
            t5$ = using$(f$,accum)      : t5$ = remove$(t5$," ")
    
            te$ = space$(2) + using$("###",month)
            te$ = te$ + space$(13 - len(t1$)) + t1$
    
            for x = len(te$) to 31 - len(t2$)
            te$ = te$ + " "
            next x
    
    	te$ = te$ + t2$
            for x = len(te$) to 46 - len(t3$)
            te$ = te$ + " "
            next x
    	te$ = te$ + t3$
    
            for x = len(te$) to 59 - len(t4$)
            te$ = te$ + " "
            next x
            te$ = te$ + t4$
    
            for x = len(te$) to 74 - len(t5$)
            te$ = te$ + " "
            next x
            te$ = te$ + t5$
    
    	put$ #1,te$ + crlf$
    rem	print;te$
            if principal <= 0 then exit for
            if month / 12 = int(month / 12) then
            put$ #1,string$(75,"-") + crlf$
            end if
            next month
            close #1
    
    	m$ = "Finished writing to " + chr$(34) + "AMORT.TXT" + chr$(34)
            m$ = m$ + " file."
            col = 40 - int(len(m$) / 2)
            locate 20,col : print;m$;
    
    REM     I didn't include an LPRINT routine since a lot of printers
    REM     are of the USB variety. Can't get there from here.
    
            m$ = "Bring up your favorite ASCII word processor to print it out."
            col = 40 - int(len(m$) / 2)
            locate 21,col
            print;m$;
    
            end if
    
            m$ = "Tap ESCape to end or any other key to compute another"
            col = 40 - int(len(m$) / 2)
            locate 22,col
            print;m$
    
            t = abort
            if t = 1 then exit loop
            loop
    
            end
    
    function abort
    	while instat=0:wend
            an$ = inkey$
            if an$ = chr$(27) then
            function = 1
            else
            function = 0
            end if
            end function

    ------------------




    [This message has been edited by Mel Bishop (edited August 03, 2004).]

    Leave a comment:


  • Michael Mattias
    replied
    > it seems to be with the ?rounding errors? in the calcuations

    since you refuse to post even a piece of code (fwiw, amortization is hardly a trade secret), just check your data types.

    if float? you have rounding problems, and you must handle them.

    you have it easy, because you know about the need to round your floats.

    i had it a little tougher because i had to find a little problem in the compiler first:

    http://www.powerbasic.com/support/pb...ad.php?t=24241

    (fwiw, there's some rounding code in there you can probably use).


    Leave a comment:


  • Mel Bishop
    replied
    Thanks for the tips MM but no go. There's nothing wrong with
    the loop counters. They work as advertised. It seems to be
    with the ?rounding errors? in the calcuations.

    If anyone has a commercial loan program, could you please enter
    the following values and see if it bleeds over to 361 months on
    your program.

    Loan amount: $80,000
    Term: 30 years (360 months)
    Interest: 5.5 percent APR

    This bleed over doesn't happen all the time. Just occasionally.


    ------------------

    Leave a comment:


  • Michael Mattias
    replied
    You might also consider changing to the FIX datatype with FIXDIGITS=4, which gives you the equivalent of a CURRENCY datatype... which of course is perfect for money calculations.

    Leave a comment:


  • Michael Mattias
    replied
    Check all loop counters (FOR...NEXT) and WHILE/DO..WHILE|UNTIL.

    Make sure all 'end of loop' conditions are integer; or, the 'done with the loop' comparison is made against a difference, like:
    Code:
      DO UNTIL ABS(lastval# - thisval#) < .00001!
    .. or something like that.

    Hopefully, you have not written too much code using something like..
    Code:
      IF Z# < | > |= X# THEN
         [b]EXIT FOR[/b]
         ....
    .. because then you'll have to go through your code line-by-line looking for any statement in which you do a numeric comparison of non-integers.

    MCM

    Leave a comment:


  • Mel Bishop
    started a topic ?Rounding errors?

    ?Rounding errors?

    Because of a recent post, I decided to dust off and polish up
    an old loan amortization program that I wrote some years ago.
    Now to the best of recollation, the old program, written in
    PB/DOS 2.1f was accurate down to the penny right up to the last
    month of the repayment period.

    With PB/DOS 3.5, under certain circumstances, an error occurs
    that I haven't been able to narrow down.

    For example, if I enter loan data for 30 years, (360 months),
    it sometimes over-runs to 361 months. Now I assume this is due
    to rounding errors but I haven't been able to "debug" this and
    it's driving me nuts. Can anyone give me some ideas without me
    posting the source code? TIA.

    BTW: I don't have 2.1f anymore. I lost it after I found out
    that windows, by default, doesn't backup .EXE files.


    ------------------
Working...
X
😀
🥰
🤢
😎
😡
👍
👎