*BSD News Article 2921


Return to BSD News archive

Xref: sserve comp.lang.c:30816 comp.sys.amiga.programmer:17626 comp.unix.bsd:2965
Newsgroups: comp.lang.c,comp.sys.amiga.programmer,comp.unix.bsd
Path: sserve!manuel!munnari.oz.au!sgiblab!sdd.hp.com!usc!snorkelwacker.mit.edu!bloom-picayune.mit.edu!news
From: scs@adam.mit.edu (Steve Summit)
Subject: Re: Matt Dillon's DICE (Amiga C) and rand() function
Message-ID: <1992Jul31.220141.3595@athena.mit.edu>
Followup-To: comp.lang.c,comp.unix.bsd
Sender: news@athena.mit.edu (News system)
Nntp-Posting-Host: adam.mit.edu
Organization: none, at the moment
References: <1992Jul30.214117.27748@athena.mit.edu> <1992Jul31.112751.6735@email.tuwien.ac.at>
Date: Fri, 31 Jul 1992 22:01:41 GMT
Lines: 66

In article <1992Jul31.112751.6735@email.tuwien.ac.at>, hp@vmars.tuwien.ac.at (Peter Holzer) writes:
> Also, many implementations of rand (e.g. the one in BSD, and (I think)
> the example in the standard), have the property that they produce a
> cycle of length n if n is a divisor of RAND_MAX + 1. So rand % 2 will
> give you 0 and 1 alternately, which does not look very random.

Indeed.  I forgot to mention this in my list of random caveats.
(The example in the Standard is okay, by the way, at least the
one in section 4.10.2 on page 155: it divides an unsigned long
int state variable by 65536, extracting some higher-order bits,
before taking it modulo RAND_MAX+1.)

Am I the only one who considers this a bug in BSD that should
have fixed long ago?  Why shouldn't programmers be able to use
the obvious

	rand() % 2

to flip coins?

I've heard that the original ports of Unix from the PDP-11 to the
VAX adopted a slight modification of the old PDP-11 rand() code,
which had returned a 16-bit value from the *high* half of a 32-bit
state variable, precisely to avoid cycles in the low-order bits.
Since ints are 32 bits on the VAX, someone figured that all 32
bits of the state variable could be returned, and out came the
non-random bits.

I have this memory of an intricate series of apologies in one of
the "Bug Fixes and Changes in 4.nBSD" documents, probably for
4.2, discussing how a bug fix in the random number generator had
resulted in a change to crypt()'s behavior which had changed the
way passwords were encoded which meant that the passwd file had
to rebuilt and/or everybody had to re-enter their passwords.
It would have been nice if this bug fix had patched up or shifted
off those non-random low-order rand() bits, yet they're still
there today, and BSD programmers are encouraged to use the more
random but nonstandard random() routine instead.  Why not just
fix rand(), or replace it with random()'s algorithm?  (It is in
hopes of receiving an answer to this question that I am
crossposting to comp.unix.bsd .)

Peter continued, in response to another code fragment of mine:
>> One legitimate use of RAND_MAX is generating random floating-
>> point numbers; for example,
>>
>> 	rand() / (double)(RAND_MAX - 1)
>>
>> should give randomly distributed numbers over the range 0..1 .
>
> If you want a random value in the range [0, 1] you must divide by
> RAND_MAX, if you want a range of [0, 1), divide by (RAND_MAX + 1).

Oops.  Peter's quite right; I must have been thinking that rand()
returned numbers greater than or equal to 0 but strictly less
than RAND_MAX (i.e. in the range [0, RAND_MAX), as if the rand()
implementation had returned a value modulo RAND_MAX.  The
documentation for rand(), even in the ANSI Standard, always says
that it returns numbers "in the range 0 to RAND_MAX"; it should
really be explicit and say ", inclusive").

This has nothing to do with the Amiga any more, so I've
redirected followups.

					Steve Summit
					scs@adam.mit.edu