--- title: "Loan Amortization 2068" id: 55046 type: "computer_media" slug: "loan-amortization-2068" url: "http://localhost/computer_media/loan-amortization-2068/" markdown_url: "http://localhost/computer_media/loan-amortization-2068.md" published_at: "2024-06-11T13:41:03+00:00" modified_at: "2026-03-31T14:40:46+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/06/SCR-20260330-lvnd.png" excerpt: "Enter a loan amount, term, and interest rate to get a fully formatted amortization schedule showing payment-by-payment interest, principal, and balance breakdowns." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Imre Auersbacher" slug: "imre-auersbacher" taxonomy: "indiv" url: "http://localhost/indiv/imre-auersbacher/" genre: - name: "Finance" slug: "finance" taxonomy: "genre" url: "http://localhost/type/finance/" media_contents: - id: 55036 title: "TS-2068 Computer Programs" type: "computer_media" url: "http://localhost/computer_media/ts-2068-computer-programs/" media_type: "Program" programmers: - name: "Imre Auersbacher" slug: "imre-auersbacher" taxonomy: "indiv" url: "http://localhost/indiv/imre-auersbacher/" mediadate: "1985" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20260330-lvnd.png" media_type_tags: "Finance" --- # Loan Amortization 2068 This program computes and displays a complete loan amortization schedule, showing the interest, principal, and remaining balance for each monthly payment period. It accepts three inputs — loan amount, number of periods, and annual interest rate — then applies the standard annuity formula to derive the monthly payment and iterates through each period. Two user-defined functions handle numeric rounding to the nearest cent (`FN a`) and string formatting to ensure consistent two-decimal-place display (`FN a$`). The schedule is printed in a right-justified columnar layout using `TAB` expressions computed from string lengths, and a summary section reports total loan amount, total interest paid, and total payments made. *** ## Program Analysis ### Program Structure The program is organized into a linear sequence of input, calculation, and output phases, with a single reusable formatting subroutine at line `20`: 1. **Initialization (lines 10–18):** REM headers, function definitions, and variable setup. 2. **Input (lines 25–60):** Prompts for loan amount (`a`), number of periods (`n`), and annual interest rate (`y`), then converts the rate to a monthly decimal. 3. **Payment calculation (line 65):** Derives monthly payment `p` using the annuity formula and total interest `d`. 4. **Amortization loop (lines 80–115):** Iterates from period 1 to `n`, computing balance, interest, and principal for each period. 5. **Summary (lines 120–125):** Prints loan amount, total interest, and total payments. 6. **Formatting subroutine (line 20):** Called via `GO SUB 20` to round `x` and produce a formatted string `c$`. ### Mathematical Approach The monthly payment is derived at line `65` using the standard present-value annuity formula: `p = a * (y / (1 - (1+y)^(-n)))` where `y` is the monthly interest rate (`y/1200` of the annual percentage). The remaining balance at period `z` is computed directly at line `80` using the closed-form expression: `b = (1+y)^z * (p*(((1+y)^(-z))-1)/y + a)` This avoids accumulating floating-point errors that would arise from iterative subtraction over many periods. The guard at line `85` clamps near-zero balances to exactly zero. ### User-Defined Functions | Function | Definition | Purpose | | --- | --- | --- | | `FN a(x)` | `INT(c*x+0.5)/c` | Rounds `x` to the nearest cent (uses global `c=100`) | | `FN a$(x,c$)` | Appends `".00"` or `"0"` as needed | Ensures the string always has two decimal places | Note that `FN a$` takes a parameter also named `c$`, which shadows the global variable `c$` within the function. The logic `(".00" AND x=INT x)` appends `".00"` when the value is a whole number, and `("0" AND ("0"+c$)(LEN c$)=".")` appends a trailing `"0"` when the string has only one decimal digit — exploiting the Spectrum’s string Boolean idiom where a true condition returns the string and false returns an empty string. ### Formatting Subroutine Lines `20` is a two-statement subroutine called repeatedly: it rounds the global `x` via `FN a`, then formats the result as a string via `FN a$`, storing it in `c$`. The caller sets `x` before each `GO SUB 20` and reads back `c$` afterward. This pattern is used for `i$`, `p$`, and `b$` (interest, principal, balance strings) in lines `95`–`105`. ### Columnar Output with TAB Line `110` right-justifies each column by computing the tab stop dynamically: `TAB (3-LEN STR$ z)`, `TAB (12-LEN i$)`, `TAB (21-LEN p$)`, `TAB (32-LEN b$)` This ensures that numbers of different widths align on their right edge within fixed column positions, without requiring a fixed-width number format. The separator line at line `75` uses a row of block graphic ▀ characters to draw a visual rule under the column headers. ### Miscellaneous Techniques and Notes - Line `70` uses `POKE 23692,1` to suppress the `scroll?` prompt, allowing the schedule to scroll uninterrupted regardless of its length. - The `BEEP 0.07,22` at line `18` provides a short startup sound on initialization. - Line `100` ends with a bare colon, which is syntactically harmless but slightly untidy. - Line `130` has a redundant second `STOP` statement; only the first is ever reached. - The variable `t=23` set at line `35` is used in lines `120`–`125` as the right-edge tab column for the summary section, keeping those values right-aligned at column 23. - Line `200` saves the program with `LINE 10`, designating line `10` as the auto-start line. ## Source Code ``` 10 REM Loan Amortization 2068 12 REM \* 1984 I. Auersbacher 14 DEF FN a(x)=INT (c*x+0.5)/c 16 DEF FN a$(x,c$)=c$+(".00" AND x=INT x)+("0" AND ("0"+c$)(LEN c$)=".") 18 BORDER 5: LET c=100: LET x=0: BEEP 0.07,22: CLS : GO TO 25 20 LET x=FN a(x): LET c$=FN a$(x,STR$ x): RETURN 25 PRINT PAPER 6;"** Loan Amortization Schedule **": PRINT 30 PRINT "Loan Amount : $"; 35 INPUT a: PRINT a: LET t=23 40 PRINT "No. Periods : "; 45 INPUT n: PRINT n;" months" 50 PRINT "Interest (%): "; 55 INPUT y: PRINT y 60 LET y=y/1200: PRINT 65 LET p=a*(y/(1-(1+y)^(-n))): LET x=p: GO SUB 20: LET d=n*p-a 70 PRINT "Monthly Pymt= $";c$: POKE 23692,1: PRINT : LET l=a 75 PRINT "Pmt Interest Principal Balance": PRINT "\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''" 80 FOR z=1 TO n: LET k=(1+y)^(-z): LET b=1/k*(p*(k-1)/y+a) 85 IF b<0.001 THEN LET b=0 90 LET i=b-l+p: LET r=p-i 95 LET l=b: LET x=i: GO SUB 20 100 LET i$=c$: LET x=r: GO SUB 20: LET p$=c$: LET x=b: 105 GO SUB 20: LET b$=c$ 110 PRINT TAB (3-LEN STR$ z);z;TAB (12-LEN i$);i$;TAB (21-LEN p$);p$;TAB (32-LEN b$);b$ 115 NEXT z: PRINT : PRINT 120 LET x=a: GO SUB 20: PRINT "Loan Amount =";TAB t-LEN c$;c$ 125 LET x=d: GO SUB 20: PRINT "Tot.Interest=";TAB t-LEN c$;c$: LET x=n*p: GO SUB 20: PRINT "Total paymts=";TAB t-LEN c$;c$ 130 STOP : STOP 200 SAVE "loans" LINE 10 ```