Decimal Columns is a BASIC program that accepts a numeric input and prints it right-aligned across multiple screen columns, formatted to exactly two decimal places. The core formatting logic uses two DEF FN functions: one rounds a number to two decimal places using the INT(100*K+0.5)/100 technique, and a second constructs the display string by appending “.00” when the value is a whole number, or a trailing “0” when only one decimal digit is present. Lines 110–140, which divide and multiply the input to generate derived values for columns 2 and 3, are marked optional and can be removed for single-column output. The TAB positioning arithmetic (e.g., TAB 10-LEN K$) achieves right-alignment by subtracting the string length from the target column stop.
Program Structure
The program is organized into three functional blocks: setup and display (lines 10–90), the main input-and-print loop (lines 90–150), and the formatting subroutine with its supporting function definitions (lines 160–200). Lines 10–50 are entirely REM statements serving as documentation. Line 60 clears the screen and prints a header. The main loop at lines 90–150 accepts a number, formats and prints it up to three times, then loops back to GO TO 90.
Column Layout
Three columns are produced at TAB stops 10, 20, and 30. Right-alignment within each column is achieved by the expression TAB 10-LEN K$ (and analogously for 20 and 30), so that the last character of the formatted string always lands on the column boundary. Lines 110–140, which compute derived values (K/3 and that result times 2) for columns 2 and 3, are flagged in the REMs as optional; removing them reduces the output to a single right-aligned column.
Formatting Subroutine
The subroutine at line 160 calls two DEF FN functions in sequence and returns the formatted string in K$:
DEF FN K(K) = INT(100*K+0.5)/100(line 170) — rounds the value to two decimal places using the classic multiply-round-divide idiom. The comment in line 190 correctly notes that changing 100 to 1000 would extend precision to three decimal places.DEF FN K$(K,K$) = K$+(".00" AND K=INT K)+("0" AND ("0"+K$)(LEN K$)=".")(line 180) — appends the necessary suffix to the numeric string. The first term adds.00when the rounded value is a whole number. The second term appends a trailing0when the last character ofK$is a decimal point, covering cases like “3.5” displayed as “3.50”. The string Boolean idiom ("text" AND condition) is standard Spectrum BASIC practice.
Key BASIC Idioms
- Right-alignment via TAB arithmetic:
PRINT TAB 10-LEN K$;K$;is a concise one-expression right-align for a fixed column width. - String Boolean padding: Using
ANDwith a string literal to conditionally concatenate text is a well-known Spectrum idiom that avoids IF/THEN branching. - Trailing semicolon: Each
PRINTstatement ends with;to suppress the newline, allowing all three column values to appear on the same line. - Chained DEF FN calls: The subroutine applies two sequential function calls, using the same variable name
Kas both the FN parameter and the main variable, which is valid in Spectrum BASIC but requires careful reading.
Notable Anomalies and Observations
Line 90 reads INPUT "ENTER A NUMBER: ";k (lowercase k), which is the same variable as the uppercase K used throughout — on the Spectrum these are the same variable, so this is not a bug. However, line 100 references K$ before it has been assigned by the subroutine at line 160; this means the first column always prints the previous iteration’s formatted string rather than the freshly entered value. To print the entered value correctly in column 1, line 100 should call GO SUB 160 before the PRINT, or lines should be reordered so the subroutine runs first.
The keyword LINE 60 in the SAVE command at line 210 causes the program to auto-run from line 60 when loaded.
Several lines use conditional compilation-style comments (lines marked with embedded REM tokens in the middle of lines) to annotate optional sections, a creative if unconventional documentation approach in BASIC.
Line Reference Table
| Line(s) | Role |
|---|---|
| 10–50 | REM documentation blocks |
| 60 | CLS and screen header |
| 90 | INPUT prompt for number K |
| 100 | Print column 1 (right-aligned at TAB 10) |
| 110–120 | Derive K/3, format, print column 2 (optional) |
| 130–140 | Derive ×2, format, print column 3 (optional) |
| 150 | Loop back to INPUT |
| 160 | Formatting subroutine entry/exit |
| 170 | DEF FN K — two-decimal rounding |
| 180 | DEF FN K$ — decimal string padding |
| 190–200 | REM explanations of lines 170 and 180 |
| 210 | SAVE with auto-run |
Content
Source Code
10 REM \{16}\{2}THIS PROGRAM IS PRESENTED BY ALGIS E. GEDRIS\{16}\{0}
20 REM \{16}\{4}NUMBER PRINTOUT ON THE SCREEN IN COLUMNS\{16}\{0}
30 \{20}\{0}\{20}\{0}\{20}\{1} REM \{20}\{0}SETING UP FOR NUMBER PRINT-OUT IN DIFFERENT COLUMNS
40 \{20}\{1} REM \{20}\{0}\{20}\{1}\{20}\{0}LINES 110 THROUGH 140 CAN BE ELIMINATED FOR ONE COLUMN PRINTOUT
50 \{20}\{1} REM \{20}\{0} ALL \{20}\{1} REM \{20}\{0} STATEMENTS CAN BE ELIMINATED.
60 CLS :PRINT AT 3,0;"PRINT-OUT ANY DECIMALS NUMBERS IN COLUMNS"
90 INPUT "ENTER A NUMBER: ";k
100 PRINT TAB 10- LEN K$;K$;
110 \{20}\{1} LET K=K/3:GO SUB 160\{20}\{0}
120 \{20}\{1} PRINT TAB 20- LEN K$;K$;\{20}\{0}
130 \{20}\{1} LET K=K*2:GO SUB 160\{20}\{0}
140 \{20}\{1} PRINT TAB 30- LEN K$;K$;\{20}\{0}
150 GO TO 90
160 LET K= FN K(K):LET K$= FN K$(K, STR$ K):RETURN
170 DEF FN K(K)= INT (100*K+0.5)/100
180 DEF FN K$(K,K$)=K$+(".00" AND K= INT K)+("0" AND ("0"+K$)(LEN K$)=".")
190 \{20}\{1} REM \{20}\{0}IN LINE 170 THE NUMBER "100" DIFINES THAT ONLY TWO SIGNIFICANT NUMBERS WILL BE SHOWN.CHANGING 100 TO 1000 (TWO PLACES) WILL GIVE THREE SIGNIFICANT NUMBER PRINTOUT.
200 \{20}\{1} REM \{20}\{0}LINE 180 ADDS .00; (.5)0 AND "." TO THE NUMBER.
210 SAVE "DECIMALCOL" LINE 60
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
