bad random generation

CSSE LAN Test Account lan_csse at netrix.nac.dec.com
Sat May 25 01:54:22 AEST 1991


>yedidya at bimacs.BITNET (Yedidya Israel) writes:
>>        Recently I used the random generator  random()  with the default
>>seed to generate input for sorting programs.  While scanning the results,
>>I noticed two pairs of very close numbers in the output.  When I then
>>reviewed the input, I was disturbed to find that these numbers came from
>>nearby positions in the input list, in positions 26 and 29, 27 and 30,
>>respectively.  Since I am not an expert in random number generation, I
>>should appreciate your reaction.

In addition to the Knuth books, here is a routine that I've been passing
around for some time.  You might install it in your libraries in place of
the rand() routine; for your own applications, you can just call minrand()
directly.  There are probably lots more around...

 - - - - - - - - - - - - C U T - H E R E - - - - - - - - - - - - - - - - - - -
/*		minseed(s);
**		i = minrand();
** This is the "minimal standard random" routine by Stephen K. Park and Keith
** W. Miller, in "Random number generators: good ones are hard to find", in
** the Oct 1988 CACM (v.31, no.10).  The authors make a good case that this
** is the minimally-acceptable pseudorandom-number generator, as it is highly
** random by all common statistical tests, and has a sufficiently long period
** (2 ^ 31 - 2) for almost all applications.  They suggest installing in in
** all libraries in place of the (usually deficient) routines supplied by most
** vendors, and to use an alternate routine only if it is KNOWN to be better.
**
** You are encouraged to give this source code to anyone who wants it.  There
** is no copyright.  It was typed in by John Chambers in C while reading the
** above article, and I don't think the authors will make any claims on the
** code as long as we continue to give them credit.
**
** This version returns a long int in the range [1..2147483646].
**
** Any int in the range [1..2147483646] may be used as a seed.  To get a unique
** sequence, use an initialization like minseed(getpid()) or minseed(time(0L)).
** For a reproducible sequence, ask the user for a seed, and encourage them to
** use something memorable like their Social Security number.  Do not use zero,
** as the result will be a sequence of all zeroes.  Note that the upper bound
** is 0x7FFFFFFE, which you may find easier to type.
**
** If compiled with -DTEST, a test driver is compiled that performs the check 
** they suggest of starting with seed=1, calculating 10,000 random numbers, 
** and verifying the resulting seed.  I'd suggest running the test program
** via the command:
**		time minrand
** and dividing the results by 10,000.  This gives you approximately the time
** to make one minrand() call.
*/
#define A 16807			/* Multiplier */
#define M 2147483647	/* Modulus */
#define Q 127773		/* M / A */
#define R 2836			/* M % A */

static seed = 1;

minseed(s) long s; { seed = s; }

long
minrand()
{	long lo, hi, test;

	hi = seed / Q;
	lo = seed % Q;
	test = (A * lo) - (R * hi);
	seed = (test > 0)? test: test + M;
	return seed;
}
#ifdef TEST
#include <stdio.h>
#define testseed 1043618065	/* Seed 10,001 */

main()
{	int n;

	for (n=1; n<=10000; n++)
		minrand();
	if (seed == testseed)
		 fprintf(stderr,"The 10,001st seed is correct: %ld.\n",seed);
	else fprintf(stderr,"The 10,001st seed is incorrect: %ld.\n",seed);
	exit(seed != testseed);
}
#endif



More information about the Comp.unix.questions mailing list