This program is a multi-section mathematics toolkit covering eight topics: greatest common divisor (Euclidean algorithm), least common multiple, prime factorisation, quadratic equations, zero-finding for functions, polynomial evaluation, polynomial multiplication, and function plotting. The zero-finding routine (lines 1440–1750) uses a sign-change bisection method with user-supplied interval, step size, and epsilon tolerance. The polynomial evaluator (lines 1940–1990) applies Horner’s method for efficient computation. The function plotter (lines 2820–2890) maps mathematical coordinates to the 64×44 pixel display grid using scaling factors MX and MY, and plots the hardcoded function sin(x)+sin(2x).
Program Analysis
Program Structure
The program is organised as a menu dispatcher with eight numbered sections. Lines 2–120 display the main menu, line 150 calls the key-reading subroutine at 8800, and lines 155–190 dispatch to each section via a chain of IF … THEN GOTO statements. Each section ends by calling the “press a key” subroutine at 9000, which offers return-to-index or re-run of the current section.
| Menu Option | Topic | Start Line |
|---|---|---|
| 1 | Greatest Common Divisor | 200 |
| 2 | Smallest Common Multiple | 400 |
| 3 | Prime Factoring | 700 |
| 4 | Quadratic Equation | 1000 |
| 5 | Zeroes of a Function | 1300 |
| 6 | Value of a Function | 1800 |
| 7 | Polynomial (multiplication) | 2100 |
| 8 | Plot of Functions | 2500 |
Key Input Subroutine (line 8800)
The subroutine at line 8800 polls INKEY$ in a tight loop, rejecting any character outside “1”–”8″. Once a valid digit is detected it reads INKEY$ a second time at line 8810 with LET W=VAL INKEY$ to convert it to a number. This introduces a potential race condition: if the key is released between lines 8800 and 8810, INKEY$ returns an empty string and VAL "" yields 0, sending the dispatcher to an unmatched branch. In practice SLOW mode makes this unlikely but it is a latent bug.
Greatest Common Divisor (lines 200–330)
The implementation is the classic Euclidean algorithm: compute quotient Q=INT(A/B), remainder R=A-Q*B, reassign A=B, B=R, and loop while R>0. The result is left in A and printed as “LCD=” (a labelling quirk — the correct abbreviation for Largest Common Divisor/Greatest Common Divisor is GCD or HCF).
Smallest Common Multiple (lines 400–620)
The SCM routine uses brute-force trial: starting from X=A, it increments X by 1 until X is divisible by all three inputs A, B, and C. Each divisibility test restarts the scan from the current X (via GOTO 510) rather than continuing forward, which is correct behaviour. This approach is slow for large inputs but straightforward.
Prime Factorisation (lines 700–930)
The routine at line 800 takes the absolute value of the input, then iterates I from 2 to the original value Z. For each candidate divisor, an inner loop repeatedly divides and counts the multiplicity N. A running product T tracks how much of the number has been accounted for; when T=E (the original absolute value) the outer FOR loop is exited early via GOTO 910. Negative inputs are handled by printing a leading minus sign before the factorisation.
Quadratic Equation (lines 1000–1220)
The discriminant is computed as Q=B*B-4*A*C. If negative, “NO REAL SOLUTION” is printed. Otherwise the formula is evaluated as Q=SQR Q/(2*A) and C=-B/(2*A), giving X1=C+Q and X2=C-Q. Note that operator precedence means SQR Q/(2*A) is parsed as (SQR Q)/(2*A), which is the intended formula.
Zero-Finding by Bisection (lines 1300–1780)
This section implements a sign-change bisection search. The outer scan (lines 1440–1600) steps across the interval [XA, XE] with step H, calling the function subroutine FCT at line 1610 and watching for a sign change in Y. When a sign change is detected, the bisection refinement subroutine SFZ at line 1640 narrows the bracket until ABS(Y) < E. The function itself is hardcoded at line 1620 as Y = X³ - 4X² - 11X + 30, which has roots at x = -3, 2, and 5. FAST mode is engaged for the numerical search and SLOW restored afterwards.
Subroutine addresses are stored in variables (LET FCT=1610, LET SFZ=1640) and called with GOSUB FCT — a notable technique exploiting the fact that GOSUB accepts a numeric variable as its target line number.
Polynomial Evaluation — Horner’s Method (lines 1800–2090)
Coefficients are stored in array W() with W(1) holding the constant term A(0). The evaluation at lines 1940–1990 applies Horner’s scheme: initialise with the leading coefficient, then repeatedly multiply by X and add the next coefficient working down to degree 1, finally adding W(1). This minimises multiplications compared to naive power evaluation.
Polynomial Multiplication (lines 2100–2495)
Two polynomials are entered separately. The first polynomial’s coefficients are copied into array A() of size K+1. The product array E() is initialised to zero, then the convolution sum E(I+J-1) += W(I)*A(J) is computed for all pairs (I,J). The result is printed as a list of coefficients E(0) through E(K+N). This is a correct discrete convolution of the coefficient arrays.
Function Plotter (lines 2500–2950)
The plotter draws axes at pixel position (31, 22) — roughly centred on the 64×44 display. Scaling factors are computed as MX=63/|XE-XA| and MY=43/|YE-YA|. The plotted function is hardcoded at line 2840 as Y = SIN(X) + SIN(2*X). Coordinate transformation applies at lines 2850–2860: X = X*MX + X0, Y = Y*MY + Y0. A bounds check at line 2870 prevents PLOT errors for out-of-range points.
Navigation Subroutine (line 9000)
The subroutine at 9000 displays a two-line prompt, waits with PAUSE 30 to debounce, then enters an INKEY$ poll loop. Pressing “R” returns to the main menu index (line 5, which is the REM crediting the source book). Any other key returns to the caller for re-entry of the same section. Line 9040 (SAVE "1024%1") is unreachable dead code following the conditional returns.
Notable Techniques and Anomalies
- Variable-target
GOSUB FCT(lines 1450, 1500, 1540, 1670) stores line numbers in variables — an efficient and flexible dispatch mechanism. FAST/SLOWmode switching (lines 1310 and 1760) is used only in the zero-finding section, where the iterative bisection benefits most from faster execution.- The SCM section accepts three inputs but the algorithm restarts from
X=Arather than incrementing by A; for large coprime numbers this will be very slow. - The prime factorisation loop iterates
FOR I=2 TO Zusing the original (potentially large) value of Z rather than the progressively reduced quotient, making it inefficient for numbers with large prime factors. - The key-reading race condition at lines 8800–8810 (double
INKEY$read) could returnW=0, causing all dispatch conditions at lines 155–190 to fail silently and loop back to the menu display. - Section 6 (“Value of a Function”) shares the polynomial input subroutine code with section 7 but duplicates it at lines 1830–1930 rather than sharing lines 2130–2230, increasing program size unnecessarily.
Content
Source Code
2 SLOW
5 REM "FROM BOOK BY ING. WINFRIED HOFACKER PUBLISHING COMPANY"
10 CLEAR
15 CLS
20 PRINT "WELCOME TO MATHEMATICS"
25 PRINT
30 PRINT "PRESS DESIRED SELECTION NUMBER"
35 PRINT
40 PRINT "1> LARGEST COMMON DIVISOR"
45 PRINT
50 PRINT "2> SMALLEST COMMON MULTIPLE"
55 PRINT
60 PRINT "3> PRIME FACTORING OF NUMBERS"
65 PRINT
70 PRINT "4> QUADRATIC EQUATION"
75 PRINT
80 PRINT "5> ZEROES OF A FUNCTION"
85 PRINT
90 PRINT "6> VALUE OF A FUNCTION"
95 PRINT
100 PRINT "7> POLYNOMIAL"
105 PRINT
110 PRINT "8> PLOT OF FUNCTIONS"
120 PRINT AT 21,4;" RUN IN SLOW MODE"
150 GOSUB 8800
155 IF W=1 THEN GOTO 200
160 IF W=2 THEN GOTO 400
165 IF W=3 THEN GOTO 700
170 IF W=4 THEN GOTO 1000
175 IF W=5 THEN GOTO 1300
180 IF W=6 THEN GOTO 1800
185 IF W=7 THEN GOTO 2100
190 IF W=8 THEN GOTO 2500
200 CLS
205 CLEAR
208 PRINT "LARGEST COMMON DIVISOR"
209 PRINT
210 PRINT "A=";
220 INPUT A
230 PRINT A
240 PRINT "B=";
250 INPUT B
260 PRINT B
270 LET Q=INT (A/B)
280 LET R=A-Q*B
290 LET A=B
300 LET B=R
310 IF R>0 THEN GOTO 270
320 PRINT "LCD=";A
325 GOSUB 9000
330 GOTO 200
400 CLS
405 CLEAR
408 PRINT "SMALLEST COMMON MULTIPLE"
409 PRINT
410 PRINT "A=";
420 INPUT A
430 PRINT A
440 PRINT "B=";
450 INPUT B
460 PRINT B
470 PRINT "C=";
480 INPUT C
490 PRINT C
500 LET X=A
510 IF INT (X/A)=X/A THEN GOTO 540
520 LET X=X+1
530 GOTO 510
540 IF INT (X/B)=X/B THEN GOTO 570
550 LET X=X+1
560 GOTO 510
570 IF INT (X/C)=X/C THEN GOTO 600
580 LET X=X+1
590 GOTO 510
600 PRINT "SCM=";X
610 GOSUB 9000
620 GOTO 400
700 CLS
705 CLEAR
708 PRINT "PRIME FACTORING OF NUMBERS"
710 PRINT
720 PRINT "NUMBER=";
730 INPUT Z
740 PRINT Z
750 PRINT Z;"=";
760 IF Z<0 THEN PRINT "-";
770 PRINT "1";
800 LET Z=ABS Z
805 LET E=Z
808 LET T=1
810 FOR I=2 TO Z
820 LET N=0
830 IF Z/I<>INT (Z/I) THEN GOTO 870
840 LET Z=Z/I
850 LET N=N+1
860 GOTO 830
870 IF N=0 THEN GOTO 900
880 FOR J=1 TO N
885 PRINT "*";I;
887 LET T=T*I
888 IF T=E THEN GOTO 910
890 NEXT J
900 NEXT I
910 PRINT
920 GOSUB 9000
930 GOTO 700
1000 CLS
1002 CLEAR
1004 PRINT "QUADRATIC EQUATION"
1006 PRINT
1008 PRINT "A*X*X+B*X+C=0"
1010 PRINT "A=";
1020 INPUT A
1030 PRINT A
1040 PRINT "B=";
1050 INPUT B
1060 PRINT B
1070 PRINT "C=";
1080 INPUT C
1090 PRINT C
1100 LET Q=B*B-4*A*C
1110 IF Q<0 THEN GOTO 1200
1120 LET Q=SQR Q/(2*A)
1130 LET C=-B/(2*A)
1140 LET X1=C+Q
1145 PRINT "X1=";
1150 PRINT X1
1160 LET X2=C-Q
1165 PRINT "X2=";
1170 PRINT X2
1180 GOSUB 9000
1190 GOTO 1000
1200 PRINT "NO REAL SOLUTION"
1210 GOSUB 9000
1220 GOTO 1000
1300 CLS
1302 CLEAR
1304 PRINT "ZEROES OF A FUNCTION"
1305 PRINT
1306 REM "FUNCTION IS FCT"
1308 REM "SEARCHING FOR ZEROES IS SFZ"
1310 FAST
1312 PRINT "XA=";
1315 INPUT XA
1320 PRINT XA
1330 PRINT "XE=";
1340 INPUT XE
1350 PRINT XE
1360 PRINT "H=";
1370 INPUT H
1380 PRINT H
1390 PRINT "EPS=";
1400 INPUT E
1410 PRINT E
1420 LET FCT=1610
1430 LET SFZ=1640
1440 LET X=XA
1450 GOSUB FCT
1460 LET YA=Y
1470 LET XA=X
1480 LET X=XA+H
1490 IF X>XE THEN GOTO 1760
1500 GOSUB FCT
1510 IF SGN Y=SGN YA THEN GOTO 1580
1520 LET YN=Y
1530 LET XN=X
1540 GOSUB SFZ
1550 PRINT "ZERO AT POSITION X=";X
1560 IF X<XE THEN LET X=X+E
1570 GOTO 1450
1580 LET YA=Y
1590 LET XA=X
1600 GOTO 1480
1610 REM FCT
1620 LET Y=X*X*X-4*X*X-11*X+30
1630 RETURN
1640 REM SFZ
1650 IF ABS (Y)<E THEN RETURN
1660 LET X=(XN-XA)/2+XA
1670 GOSUB FCT
1680 IF ABS Y<E THEN RETURN
1690 IF SGN Y=SGN YN THEN GOTO 1730
1700 LET YA=Y
1710 LET XA=X
1720 GOTO 1660
1730 LET YN=Y
1740 LET XN=X
1750 GOTO 1660
1760 SLOW
1770 GOSUB 9000
1780 GOTO 1300
1800 CLS
1805 CLEAR
1810 PRINT "VALUE OF A FUNCTION"
1815 PRINT
1820 GOTO 2000
1830 REM POLYNOMIAL
1840 PRINT "N=";
1850 INPUT N
1860 PRINT N
1870 DIM W(N+1)
1880 FOR I=1 TO N+1
1890 PRINT "A(";I-1;")=";
1900 INPUT W(I)
1910 PRINT W(I)
1920 NEXT I
1930 RETURN
1940 LET Y=W(N+1)*X
1950 FOR I=N TO 2 STEP -1
1960 LET Y=(Y+W(I))*X
1970 NEXT I
1980 LET Y=Y+W(1)
1990 RETURN
2000 GOSUB 1830
2010 PRINT "X=";
2020 INPUT X
2030 PRINT X
2040 GOSUB 1940
2050 PRINT "Y=";Y
2060 PRINT "NEW X? (Y/N)"
2070 IF INKEY$="" THEN GOTO 2070
2080 IF INKEY$="Y" THEN GOTO 2010
2085 GOSUB 9000
2090 GOTO 1800
2100 CLS
2105 CLEAR
2120 GOTO 2240
2130 REM "POLYNOMIAL"
2135 PRINT
2140 PRINT "N=";
2150 INPUT N
2160 PRINT N
2170 DIM W(N+1)
2180 FOR I=1 TO N+1
2190 PRINT "A(";I-1;")=";
2200 INPUT W(I)
2210 PRINT W(I)
2220 NEXT I
2230 RETURN
2240 PRINT "1. POLYNOMIAL"
2250 GOSUB 2130
2260 LET K=N
2270 DIM A(K+1)
2280 FOR I=1 TO K+1
2290 LET A(I)=W(I)
2300 NEXT I
2310 CLS
2320 PRINT "2. POLYNOMIAL"
2330 GOSUB 2130
2340 LET L=N+K+1
2350 DIM E(L)
2360 FOR I=1 TO L
2370 LET E(I)=0
2380 NEXT I
2390 FOR I=1 TO N+1
2400 FOR J=1 TO K+1
2410 LET L=I+J-1
2420 LET E(L)=E(L)+W(I)*A(J)
2430 NEXT J
2440 NEXT I
2450 CLS
2460 LET L=K+N+1
2470 FOR I=1 TO L
2480 PRINT "E(";I-1;")=";E(I)
2485 NEXT I
2490 GOSUB 9000
2495 GOTO 2100
2500 CLS
2505 CLEAR
2510 PRINT "PLOT"
2515 REM "PLOT OF FUNCTIONS"
2520 GOTO 2900
2530 FOR I=0 TO 63
2540 PLOT I,22
2550 NEXT I
2560 FOR I=0 TO 43
2570 PLOT 31,I
2580 NEXT I
2590 PRINT AT 0,14;"Y"
2600 PRINT AT 11,31;"X"
2610 RETURN
2620 LET X0=31
2630 LET Y0=22
2640 PRINT "XA=";
2650 INPUT XA
2660 PRINT XA
2670 PRINT "XE=";
2680 INPUT XE
2690 PRINT XE
2700 PRINT "YA=";
2710 INPUT YA
2720 PRINT YA
2730 PRINT "YE=";
2740 INPUT YE
2750 PRINT YE
2760 LET MX=63/ABS (XE-XA)
2770 LET MY=43/ABS (YE-YA)
2780 PRINT "H=";
2790 INPUT H
2800 PRINT H
2810 RETURN
2820 FOR L=XA TO XE STEP H
2830 LET X=L
2840 LET Y=SIN X+SIN (2*X)
2850 LET X=X*MX+X0
2860 LET Y=Y*MY+Y0
2870 IF X>=0 AND X<=63 AND Y>=0 AND Y<=43 THEN PLOT X,Y
2880 NEXT L
2890 RETURN
2900 GOSUB 2620
2910 CLS
2920 GOSUB 2530
2930 GOSUB 2820
2940 GOSUB 9000
2950 GOTO 2500
8800 IF INKEY$<>"1" AND INKEY$<>"2" AND INKEY$<>"3" AND INKEY$<>"4" AND INKEY$<>"5" AND INKEY$<>"6" AND INKEY$<>"7" AND INKEY$<>"8" THEN GOTO 8800
8810 LET W=VAL INKEY$
8815 RETURN
9000 PRINT AT 20,0;"PRESS <R> TO GET INDEX,PRESS ANY"
9003 PRINT AT 21,0;"OTHER KEY TO RERUN THIS SECTION"
9005 PAUSE 30
9010 IF INKEY$="" THEN GOTO 9010
9015 IF INKEY$="R" THEN GOTO 5
9020 IF INKEY$<>"R" THEN RETURN
9040 SAVE "1024%1"
9050 GOTO 2
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
