MODULE AvgLoopLen; (* Oxford Oberon-2 *) IMPORT Random, Out; PROCEDURE Fac(n: INTEGER; f: REAL): REAL; BEGIN IF n = 0 THEN RETURN f ELSE RETURN Fac(n - 1,n*f) END END Fac; PROCEDURE Power(n,i: INTEGER): REAL; VAR p: REAL; BEGIN p := 1.0; WHILE i > 0 DO p := p * n; DEC(i) END; RETURN p END Power; PROCEDURE Abs(x: REAL): REAL; BEGIN IF x < 0 THEN RETURN -x ELSE RETURN x END END Abs; PROCEDURE Analytical(n: INTEGER): REAL; VAR i: INTEGER; res: REAL; BEGIN res := 0.0; FOR i := 1 TO n DO res := res + (Fac(n,1.0) / Power(n,i) / Fac(n - i,1.0)); END; RETURN res END Analytical; PROCEDURE Averages(n: INTEGER): REAL; CONST times = 100000; VAR rnds: SET; r,count,i: INTEGER; BEGIN count := 0; i := 0; WHILE i < times DO rnds := {}; LOOP r := Random.Roll(n); IF r IN rnds THEN EXIT ELSE INCL(rnds,r); INC(count) END END; INC(i) END; RETURN count / times END Averages; VAR i: INTEGER; av,an,df: REAL; BEGIN Random.Randomize; Out.String(" Averages Analytical Diff% ");Out.Ln; FOR i := 1 TO 20 DO Out.Int(i,3); Out.String(": "); av := Averages(i);an := Analytical(i);df := Abs(av - an) / an * 100.0; Out.Fixed(av,10,4);Out.Fixed(an,11,4);Out.Fixed(df,10,4);Out.Ln END END AvgLoopLen.