--- title: "Multiples" id: 57017 type: "computer_media" slug: "multiples" url: "http://localhost/computer_media/multiples/" markdown_url: "http://localhost/computer_media/multiples.md" published_at: "2024-10-02T07:40:41+00:00" modified_at: "2026-03-30T21:20:08+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/41_Mult.png" excerpt: "Enter any number and watch its multiples highlighted among 0–99, while non-multiples are masked with block graphic characters in a clever visual trick." 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 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Mathematics" slug: "mathematics" taxonomy: "genre" url: "http://localhost/type/mathematics/" media_contents: - id: 56732 title: "Timex Sinclair Public Domain Library Tape 1001" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1001/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/41_Mult.png" media_type_tags: "Mathematics" --- # Multiples This program prints all multiples of a user-supplied number in the range 0–99, displaying them on screen with the non-multiples replaced by block graphic characters. The program prompts for any integer from 0 to 99, with a special case that substitutes 100 for 0 (since every number is a multiple of 0, which would cause a division-by-zero or trivial result). Numbers that are not multiples are rendered using ZX81 inverse-video block graphics via CHR$ values 156 and above, creating a visually distinctive display. The loop uses nested FOR loops over tens (J) and units (K) digits, reconstructing each two-digit number as 10*J+K. Line 600 saves the program with an auto-run flag, and line 610 re-runs it after saving. *** ## Program Analysis ### Program Structure The program is divided into four logical sections: 1. **Setup (lines 5–30):** Displays the title in inverse video, prompts for input, and clears the screen. 2. **Main loop (lines 100–300):** Iterates through all numbers 0–99 using nested `FOR` loops and prints results. 3. **Multiple handler (lines 500–520):** Called via `GOTO 500` when a multiple is found; prints the number using `CHR$` block graphics. 4. **Save/run stub (lines 600–610):** Saves the program with an auto-run flag, then restarts. ### Loop Mechanics Rather than a single loop from 0 to 99, the program decomposes each number into tens digit `J` (0–9) and units digit `K` (0–9), reconstructing the value as `M = 10*J+K` at line 230. Line 210 contains the escape `\66`, which is the ZX81 block graphic for character code 66 — however, in context this appears inside a `FOR` statement and is likely a stray/erroneous character that is ignored or causes a syntax quirk; the effective upper bound for `K` is 9. Line 220 adds a leading space when `J=0` to align single-digit numbers visually. ### Multiple Detection Line 240 uses the classic integer-division test: `IF INT(M/N)*N=M THEN GOTO 500`. This checks whether `M` is exactly divisible by `N` without using the `MOD` operator (unavailable in ZX81 BASIC). When a multiple is found, execution jumps to line 500; otherwise the raw number is printed at line 250. ### Block Graphic Output for Multiples Lines 500–510 print the multiples using `CHR$(J+156)` and `CHR$(K+156)`. On the ZX81, characters 156–165 are inverse-video digits (0–9), so adding 156 to each digit index produces the corresponding inverse digit character. This makes multiples visually stand out from the ordinary printed non-multiples — an effective use of the character set without any PRINT AT or attribute manipulation. ### Zero Special Case Line 110 replaces `N=0` with `N=100`. Since every integer is a multiple of 0 only in a degenerate sense (or produces division-by-zero in the test), substituting 100 ensures no number in the 0–99 range satisfies the divisibility condition, so all numbers are printed in normal video — a pragmatic workaround. ### Key BASIC Idioms and Techniques - Integer-division modulo test: `INT(M/N)*N=M` (line 240) - Inverse-digit rendering via `CHR$(digit+156)` (lines 500–510) - `GOTO 260` at line 520 re-enters the `NEXT K` line directly, continuing the inner loop after printing a multiple — this is a deliberate structured jump into the loop body. - Title displayed in inverse video using `%`-escaped characters (line 5). - After printing all results, `GOTO 10` at line 300 loops back to prompt for a new number without restarting the program. ### Bugs and Anomalies | Line | Issue | Impact | | --- | --- | --- | | 210 | `\66` block graphic escape appears at end of `FOR K=0 TO 9` | Likely a spurious character; may cause a syntax error or be silently ignored depending on interpreter behaviour. | | 270–280 | Two consecutive `PRINT` statements produce a blank line between each row of ten numbers | Cosmetic: produces double-spaced output rows; probably intentional for readability but wastes screen space. | | 110 | Substituting 100 for 0 means no multiples are ever shown when 0 is entered | Arguably incorrect — all numbers are multiples of itself if N=0 is treated as “no filter”. The substitute value 100 is outside the display range, so the output appears to show no multiples at all. | ## Source Code ``` 5 PRINT "%M%U%L%T%I%P%L%E%S" 10 PRINT "TYPE ANY NUMBER 0 TO 99" 20 INPUT N 30 CLS 100 PRINT "THE MULTIPLES OF ";N;" ARE:" 110 IF N=0 THEN LET N=100 200 FOR J=0 TO 9 210 FOR K=0 TO 9\66 220 IF J=0 THEN PRINT " "; 230 LET M=10*J+K 240 IF INT (M/N)*N=M THEN GOTO 500 250 PRINT M;" "; 260 NEXT K 270 PRINT 280 PRINT 290 NEXT J 300 GOTO 10 500 IF J>0 THEN PRINT CHR$ (J+156); 510 PRINT CHR$ (K+156);" "; 520 GOTO 260 600 SAVE "1004%1" 610 RUN ```