Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!ut-sally!husc6!think!ames!sdcsvax!ucsdhub!hp-sdd!hplabs!hpcea!hpfcdc!hpldola!hp-lsd!dag From: dag@hp-lsd.HP.COM (David Geiser) Newsgroups: comp.misc Subject: Re: anybody got a *good* random algorithm? Message-ID: <3500003@hp-lsd.HP.COM> Date: Mon, 6-Jul-87 11:10:36 EDT Article-I.D.: hp-lsd.3500003 Posted: Mon Jul 6 11:10:36 1987 Date-Received: Sat, 11-Jul-87 05:42:34 EDT References: <6552@reed.UUCP> Organization: HP Logic Systems Division - ColoSpgs, CO Lines: 168 The header pretty much says it. I'm operating on a PDP-11/73, which gives the time only down to the second, so it can't use time as a seed (actually, I guess you can get tenths of a second, but that still doesn't help). ..... May vi rot in /dev/null. ---------------------------------------------------------------------- The random # stuff that follows is from a recent edition of BYTE. I think it was done in Pascal in the article; I've re-done it in Modula-2. I think it is pretty slick and can be adapted to many different CPUs -- that's why I'm posting instead of E-mailing. I had to do some "Mickey Mouse" stuff with a 'tmp' variable to work around a compiler defect with REAL numbers. (Sorry Mickey). If I remembered who the author(s) were, I'd give credit.... sorry. dag IMPLEMENTATION MODULE utils; VAR x, y, z : INTEGER; x1,y1,z1: REAL; PROCEDURE rand ( ) : REAL; (* Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin. --John von Neumann (1951) ... Many generator use a simple multiplicative rule to generate the next number based on a fixed prime number and a multiplier. For instance, if the prime number were 30269 and the multiplier 171, you would have x(i+1) = (171*x(i)) MOD 30269 where 'i' is the iteration number (dag) ... The solution depends upon two techniques. First, consider the problem of using a high-level language. The simple generator given above can be written as x := (171 * x) MOD 30269. In practice this coding will not work adequately on all machines. The values of x are restricted to the range 1 - 30268 and therefore will fit into a 16 bit word. This is not true for 171*x, so the expression will malfunction on many machines. You could perform the above calculation "double length", but this either requires machine code or is very expensive in both time and space. If we write x in the form 177*r+s where 0<=s<=176, then 171*x = 171*s +171*177*r = 171*s + 30267*r = 171*s + 30269*r - 2*r Since 30269*r MOD 30269 = 0, (171*x) MOD 30269 = (171*s - 2*r) MOD 30269 Therefore, the statement above can be written as x := 171 * (x MOD 177) - 2 * (x DIV 177); There is one problem, however. It can return a negative number if we do not add the following: IF x < 0 THEN x := x + 30269; We now have a mechanism for making a simple generator for a 16 bit machine. We choose a prime just slightly less than 32768 and then a multiplier (around the square root of the prime). By using the above coding trick, the problem of overflow can be eliminated with the equivalent of five or six additional instrutions. But such a simple generator on its own is inadequate. It will repeat itself too soon, and its statistical properties are not near enough to those of randomness. To improve it, we need a second technique that combines two or more generators to make a new generator that is statistically superior to any of its components. To understand this method, consider the random numbers x1 and x2 in the range 0