[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