[Oberon] (small) bug in Fractions.Generate (in SmallPrograms.Mod)
Hans Klaver
hklaver at dds.nl
Sun Jun 13 18:48:35 CEST 2021
Hi all,
Some time ago I spotted a small but pesky inaccuracy in the output of the command Fractions.Generate (part of SmallPrograms.Mod in the online sources of Project Oberon). Until then I only knew the versions of this program in the books 'Programming in Oberon' and 'Programming, a Tutorial', which give the correct output.
Last December I reported this by e-mail to prof. Wirth, but I didn't get any reply. I hope he is doing well.
The online version that is part of Project Oberon gives the following output (with => pointing to the correct output):
2 .5'0
3 .3'3 => .'3
4 .25'0
5 .2'0
6 .1'6
7 .1'428571 => .'142857
8 .125'0
9 .1'1 => .'1
10 .1'0
11 .0'90 => .'09
12 .08'3
13 .0'769230 => .'076923
14 .0'714285
15 .0'6
16 .0625'0
I corrected the Oberon-07 source code as follows to let it produce the correct output
(corrected lines indicated by (**) ).
ORP.Compile @/s Fractions.Generate 16
MODULE Fractions; (*NW 10.10.07; Tabulate fractions 1/n*)
IMPORT Texts, Oberon;
CONST Base = 10; N = 32;
VAR W: Texts.Writer;
(*
(* Original version, with bug *)
PROCEDURE Generate*;
VAR i, j, m, r: INTEGER;
d: ARRAY N OF INTEGER; (*digits*)
x: ARRAY N OF INTEGER; (*index*)
S: Texts.Scanner;
BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
IF (S.class = Texts.Int) & (S.i < N) THEN
i := 2;
WHILE i <= S.i DO j := 0;
WHILE j < i DO x[j] := 0; INC(j) END ;
m := 0; r := 1;
WHILE x[r] = 0 DO
x[r] := m; r := Base*r; d[m] := r DIV i; r := r MOD i; INC(m)
END ;
Texts.WriteInt(W, i, 5); Texts.Write(W, 9X); Texts.Write(W, "."); j := 0;
WHILE j < x[r] DO Texts.Write(W, CHR(d[j] + 48)); INC(j) END ;
Texts.Write(W, "'");
WHILE j < m DO Texts.Write(W, CHR(d[j] + 48)); INC(j) END ;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); INC(i)
END
END
END Generate;
*)
(* Corrected version *)
PROCEDURE Generate*;
VAR i, j, m, r: INTEGER;
d: ARRAY N OF INTEGER; (*digits*)
x: ARRAY N OF INTEGER; (*index*)
S: Texts.Scanner;
BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
IF (S.class = Texts.Int) & (S.i <= N) THEN
i := 2;
WHILE i <= S.i DO j := 0;
WHILE j < i DO x[j] := 0; INC(j) END ;
m := 0; r := 1;
WHILE x[r] = 0 DO INC(m); (**)
x[r] := m; r := Base*r; d[m] := r DIV i; r := r MOD i (**)
END ;
Texts.WriteInt(W, i, 5); Texts.Write(W, 9X); Texts.Write(W, "."); j := 1; (**)
WHILE j < x[r] DO Texts.Write(W, CHR(d[j] + 48)); INC(j) END ;
Texts.Write(W, "'");
j := x[r]; (**)
WHILE j <= m DO Texts.Write(W, CHR(d[j] + 48)); INC(j) END ;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); INC(i)
END
END
END Generate;
BEGIN Texts.OpenWriter(W)
END Fractions.
--
Hans Klaver
More information about the Oberon
mailing list