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