Interest Calculation

Developer(s): Kristian Boisvert
Date: 1987
Type: Program
Platform(s): TS 2068

This program calculates loan amortization, computing monthly interest payments, principal reduction, and running balance over a user-specified term. It supports two modes: interest-only summary and a full month-by-month breakdown with running balance. The program includes dual printer support, toggling between a full-size 80-column printer and the TS2040 thermal printer, with formatting adjusted accordingly — notably, line 2220 trims the separator line to 32 or 80 characters based on the selected printer. A dedicated subroutine at line 8000 formats floating-point numbers into a two-decimal-place currency string, handling edge cases such as values less than 1 and numbers with only one decimal digit. Variable names with embedded spaces (e.g., `monthly interest`) are a valid BASIC identifier quirk on this platform.


Program Analysis

Program Structure

The program is organized into clearly delimited sections, each signposted with REM statements and occupying distinct line-number ranges:

Line RangePurpose
1–90Initialization and main menu loop
1000Interest-only entry point (sets TERM1=0, falls through to 2010)
2000–2230Core amortization calculation and output
3000–3020Printer type selection (Full Size / TS2040)
4000–4020Printer on/off toggle
8000–8040Currency formatting subroutine
9000–9170User input collection subroutine
9999SAVE with auto-run

Dual-Mode Calculation

The flag variable TERM1 (also referenced as term1 — case is ignored) controls which of the two modes is active. When option 1 is chosen, line 1000 sets TERM1=0 and jumps directly into the amortization loop at line 2010, bypassing the LET term1=1 at line 2000. When TERM1=0, month-by-month output and balance tracking are suppressed, and only total interest is reported at the end. When TERM1=1, full per-month detail is displayed and optionally printed.

Currency Formatting Subroutine (Lines 8000–8040)

This subroutine accepts a value in dummy and returns a formatted string in d$. It handles three cases:

  1. Whole numbers: appends ".00" directly.
  2. Values between 0 and 1 (exclusive): prepends a leading "0" (e.g., .5"0.5").
  3. One decimal place: detects this by comparing STR$ INT(dummy*10) with STR$(dummy*10); if equal, appends a trailing "0".

The rounding at line 8005 (INT(dummy*100+.5)/100) is also applied within the main loop at lines 2026 and 2085, meaning some values are rounded twice before formatting — generally harmless for currency but slightly redundant.

Printer Support

Two printer flags control output behavior: OFF (1=printer disabled, 0=enabled) and PRINTER (1=TS2040 thermal, 0=full-size 80-column). These are toggled using NOT, which maps 0↔1 cleanly. The main output section at lines 2101–2105 branches based on both flags: when using the full-size printer, line 2102–2103 right-aligns numeric fields within a fixed 80-character string Z$ using slice assignment. When using the TS2040, values are printed one per line with labels. Line 2220 uses a slice expression ( TO 0+(32 AND printer=1)+(80 AND printer=0)) to trim the separator line to the correct width for each printer type.

Notable BASIC Idioms

  • Boolean string selection: Expressions like ("s" AND term>1) and ("FULL SIZE" AND PRINTER=0) exploit the fact that boolean conditions evaluate to 1 or 0, multiplying the string by that value to produce either the string or an empty result.
  • Dual-channel PRINT: Line 2210 uses FOR g=2 TO 2+(1 AND off=0) combined with PRINT #g to print to both screen (channel 2) and printer (channel 3) in a single loop when the printer is enabled.
  • Right-justified field packing: Lines 2102–2103 use substring slice assignment (LET Z$(21-LEN P$ TO )=P$) to right-align currency values within fixed column positions in the 80-character string Z$.
  • Variable names with spaces: The identifier monthly interest (used at lines 2025–2060) contains an embedded space, which is syntactically legal in this BASIC dialect.

Bugs and Anomalies

  • Typo at line 2085: LET aomunt=INT(amount*100+.5)/100 assigns to aomunt (a misspelling of amount), so the rounding has no effect. The variable amount continues with unrounded values in subsequent calculations, while the corrected value is silently discarded into an unused variable.
  • Line 2070 special case: When amount < payment (final partial payment), the payment is capped at the remaining balance plus interest. This logic also reassigns PAYMENT, PRINCIPAL, and re-runs the formatting subroutine for both, but uses Q$ for the adjusted payment — note that Q$ is also used elsewhere for the original payment, so context matters.
  • Line 2219 double-plus: The expression STR$ m++ contains a syntactic oddity (++); in practice the second + acts as a unary positive, so this is functionally equivalent to STR$ m+ which concatenates the string with an empty continuation — not a runtime error but unusual notation.
  • Line 3002 incomplete PRINT: The PRINT AT 10,0;TAB 7;"FULL SIZE PRINTER";TAB 31; statement ends with a trailing semicolon and no closing value, which is syntactically acceptable but leaves the cursor positioned without printing a checkmark or indicator, unlike the TS2040 branch at line 3003.

Content

Appears On

Tape-based magazine.

Related Products

Related Articles

This program will help you figure out the amount of the interest on your loans… The Menu 1- Calculate interest...

Related Content

Image Gallery

Interest Calculation

Source Code

    1 REM INITIALISE
    2 DIM Z$(80): LET OFF=1: LET printer=1
    5 REM PRINT MENU
   10 INK 0: PAPER 7: BORDER 7: CLS 
   20 PRINT AT 2,6;"INTEREST CALCULATION"
   30 PRINT AT 6,0;"1- Calculate Interest Only"''"2- Calculate Interest + Balance"''"3- Select Printer ("+("FULL SIZE" AND PRINTER=0)+("TS2040" AND PRINTER=1);")"''"4- Printer "+CHR$ 20+CHR$ (NOT OFF)+"ON/"+CHR$ 20+CHR$ OFF+"OFF"''"5- Quit"
   32 PRINT AT 20,2;"Written by Kristian Boisvert"'TAB 8;"©1987 BYTE POWER"
   35 REM WAIT FOR ENTRY
   40 LET a$=INKEY$
   50 IF a$="1" THEN GO TO 1000:      REM SHOW INTEREST ONLY
   60 IF a$="2" THEN GO TO 2000: REM SHOW INTEREST + BALANCE
   80 IF a$="3" THEN GO TO 3000: REM SELECT PRINTER
   85 IF a$="4" THEN GO TO 4000: REM PRINTER ON/OFF
   86 IF a$="5" THEN STOP : REM      STOP PROGRAM
   90 GO TO 40
  997 
  998 REM CALCULATE INTEREST ONLY
  999 
 1000 LET TERM1=0: GO TO 2010: REM SAME FORMULA!
 1997 
 1998 REM CALCULATE BAL+INTEREST
 2000 LET term1=1
 2010 LET INTEREST=0: GO SUB 9000: CLS 
 2011 LET payment1=payment
 2015 IF term1=0 THEN PRINT '"Calculating..."
 2016 LET Z$="": IF TERM1=1 AND OFF+PRINTER=0 THEN LPRINT ''"MONTH      PRINCIPAL           PAYMENT          INTEREST           BALANCE"''
 2020 FOR m=1 TO term*12
 2025 LET monthly interest=amount*(rate/100)/12
 2026 LET monthly interest=INT (monthly interest*100+.5)/100
 2030 IF term1=1 THEN LET dummy=monthly interest: GO SUB 8000: LET m$=d$
 2040 LET principal=payment-monthly interest
 2050 IF term1=1 THEN LET dummy=principal: GO SUB 8000: LET p$=d$
 2060 LET interest=interest+monthly interest
 2070 IF amount<payment THEN LET PAYMENT=AMOUNT+MONTHLY INTEREST: LET PRINCIPAL=PAYMENT-MONTHLY INTEREST: LET DUMMY=PRINCIPAL: GO SUB 8000: LET P$=D$: LET DUMMY=PAYMENT: GO SUB 8000: LET Q$=D$
 2080 LET amount=amount-principal
 2085 LET aomunt=INT (amount*100+.5)/100
 2090 IF term1=1 THEN LET dummy=amount: GO SUB 8000: LET a$=d$
 2100 IF TERM1=1 THEN CLS : PRINT "Month:";m''"Principal: $";p$''"Payment: $";q$''"Interest: $";m$''"New balance: $";a$
 2101 IF TERM1=0 OR OFF+PRINTER<>0 THEN GO TO 2105
 2102 LET Z$(4-LEN STR$ M TO )=STR$ M
 2103 LET Z$(21-LEN P$ TO )=P$: LET Z$(39-LEN Q$ TO )=Q$: LET Z$(57-LEN M$ TO )=M$: LET Z$(75-LEN A$ TO )=A$
 2104 LPRINT Z$: GO TO 2108
 2105 IF term1<>0 AND PRINTER=1 AND OFF=0 THEN LPRINT '"Month:";m''"Principal: $";p$''"Payment: $";q$''"Interest: $";m$''"New balance: $";a$'"--------------------------------"
 2109 IF TERM1=1 AND OFF=1 THEN PRINT AT 21,0;"Press any key to continue": PAUSE 0
 2110 IF AMOUNT=0 THEN GO TO 2210
 2115 NEXT m
 2210 LET dummy=interest: GO SUB 8000: LET i$=d$: LET dummy=amount: GO SUB 8000: LET a$=d$: LET dummy=payment1: GO SUB 8000: CLS : FOR g=2 TO 2+(1 AND off=0): PRINT #g''"Amount of loan: $";l$''"Rate: ";rate;"%"''"Monthly payments: $";d$''"Term: ";term;" year"+("s" AND term>1)
 2219 PRINT #g;'(("Loan paid in "+STR$ m++" month"+("s" AND m>1)) AND AMOUNT=0);("Amount left on loan: $"+a$ AND amount<>0)''"Total interest paid: $";i$
 2220 NEXT g: IF OFF=0 THEN LPRINT ''"--------------------------------------------------------------------------------"( TO 0+(32 AND printer=1)+(80 AND printer=0))''
 2230 PRINT AT 21,0;"Press any key to go back to Menu": PAUSE 0: GO TO 10
 3000 REM SELECT PRINTER
 3001 CLS : PRINT ''TAB 9;"Select Printer"
 3002 IF PRINTER=0 THEN PRINT AT 10,0;TAB 7;"FULL SIZE PRINTER";TAB 31;
 3003 IF PRINTER=1 THEN PRINT AT 10,5;"TS2040 THERMAL PRINTER"
 3010 PAUSE 0: LET A$=INKEY$: IF A$=CHR$ 13 THEN GO TO 10
 3020 LET PRINTER=NOT PRINTER: GO TO 3002
 4000 REM PRINTER ON/OFF
 4001 CLS : PRINT ''TAB 9;"PRINTER ON/OFF"
 4005 IF OFF=1 THEN PRINT AT 10,10;"PRINTER OFF"
 4006 IF OFF=0 THEN PRINT AT 10,10;"PRINTER ON  "
 4010 PAUSE 0: LET A$=INKEY$: IF A$=CHR$ 13 THEN GO TO 10
 4020 LET OFF=NOT OFF: GO TO 4005
 8000 REM PUT IN 0.00 FORMAT
 8005 LET dummy=INT (dummy*100+.5)/100
 8010 LET d$=STR$ dummy: IF dummy<1 AND dummy<>0 THEN LET d$="0"+d$
 8020 IF INT dummy=dummy THEN LET d$=d$+".00": RETURN 
 8025 LET y$=STR$ INT (dummy*10): LET x$=STR$ (dummy*10)
 8030 IF x$=y$ THEN LET d$=d$+"0"
 8040 RETURN 
 9000 CLS 
 9010 PRINT ''"Amount of loan: $";
 9020 INPUT "Amount:";amount: IF amount<=0 THEN GO TO 9020
 9030 LET dummy=amount: GO SUB 8000
 9040 LET l$=d$
 9060 PRINT l$
 9070 PRINT '"Interest rate (%): ";
 9080 INPUT "Rate:";rate
 9090 IF rate<0 OR rate>100 THEN GO TO 9080
 9100 PRINT rate;"%"
 9110 PRINT '"Term (Years): ";
 9120 INPUT "Term:";term: IF term<=0 THEN GO TO 9120
 9130 PRINT term;" Year"+("s" AND term>1)
 9136 PRINT '"Monthly payments: $";
 9137 INPUT "Payment:";payment
 9138 IF payment<=0 THEN GO TO 9137
 9139 LET dummy=payment: GO SUB 8000: LET q$=d$: PRINT q$
 9140 INPUT "Is this correct? "; LINE a$
 9150 IF a$="N" OR a$="n" THEN GO TO 9000
 9160 IF a$="y" OR a$="Y" THEN RETURN 
 9170 GO TO 9140
 9999 SAVE "INTER" LINE 1

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top