home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / lang / c / 16105 < prev    next >
Encoding:
Text File  |  1992-11-08  |  6.2 KB  |  136 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!snorkelwacker.mit.edu!bloom-picayune.mit.edu!news
  3. From: scs@adam.mit.edu (Steve Summit)
  4. Subject: Re: Random Number Generator
  5. Message-ID: <1992Nov6.223901.11603@athena.mit.edu>
  6. Sender: news@athena.mit.edu (News system)
  7. Nntp-Posting-Host: adam.mit.edu
  8. Organization: none, at the moment
  9. References: <11781@hq.hq.af.mil> <1992Oct22.181426.59@front.se> <26939@dog.ee.lbl.gov>
  10. Date: Fri, 6 Nov 1992 22:39:01 GMT
  11. Lines: 123
  12.  
  13. In article <26939@dog.ee.lbl.gov>, torek@horse.ee.lbl.gov (Chris Torek) writes:
  14. > In article <1992Oct22.181426.59@front.se> per@front.se writes:
  15. >> ... The rand() function in the VMS C RTL returns nubers which are
  16. >> alternating even and odd ...
  17. > Time for another Netnews Rerun....
  18. >
  19. >> In article <1991Dec4.203704.21200@elroy.jpl.nasa.gov>
  20. >> russb@classy.nasa.gov (Russ Brill) writes:
  21. >>> When I repeatedly call rand(), I get even, odd, even, odd,...
  22. > In article <1991Dec4.214242.15508@klaava.Helsinki.FI>
  23. > torvalds@klaava.Helsinki.FI (Linus Benedict Torvalds) writes:
  24. >> This is a known problem with many (usually older) implementations of
  25. >> rand().
  26. > In fact, the sample implementation included in the ANSI C standard
  27. > does the same.
  28.  
  29. Chris may be thinking of an earlier draft.  The example
  30. implementation in the published ANSI standard (ANSI X3.159-1989,
  31. sec. 4.10.2.2, p. 155) is not a pure linear congruential random
  32. number generator; rather, it is a LCRNG with a 32-bit (or more)
  33. state value which returns 15 bits from the *top* (most
  34. significant) half.  Therefore, its actual return values are
  35. *not* subject to these particularly unfortunate regularities.
  36. (To recap: the low-order N bits of a pure LCRNG repeat with
  37. period 2-to-the-N.)
  38.  
  39. (The V7, PDP-11 Unix rand() used the same return-the-higher-
  40. order-bits technique; tragically, someone blew it when porting
  41. the code to the 32-bit VAX and changed the code to return all 32
  42. bits of the state variable, and programmers using BSD have been
  43. plagued by the problem ever since [note 1].)
  44.  
  45. > Not everyone considers it a `problem' so much as a
  46. > `limitation'.  If you want *really* random numbers, you must not use
  47. > a pseudo-random algorithm; if you want approximately-random numbers
  48. > you must decide what for and consult algorithm books, or you will
  49. > get trapped by something like this.
  50.  
  51. For what it's worth, I find this advice unnecessarily harsh, and
  52. I do consider RNG's with regularities in their low-order bits a
  53. problem.  It doesn't matter what I think, though: the heavy
  54. hitters in the algorithms world have declared that since there
  55. are so many poor RNG's out there (which there are), programmers
  56. must never do things like
  57.  
  58.     rand() % N
  59.  
  60. , but instead must use the equivalent of
  61.  
  62.     rand / (RAND_MAX / N)
  63.  
  64. , which isn't much harder, as long as you know RAND_MAX (which
  65. hasn't always been #defined in a standard way for C).
  66.  
  67. In other words, the prevailing advice is to consign rand() % N to
  68. the same dustbin that gets() has been demoted to: the code is
  69. there, and it is theoretically legal to use it, but you mustn't.
  70.  
  71. This advice is so widespread, and is assumed (here's the fallacy)
  72. to be so well-known, that there is apparently no incentive for a
  73. vendor to fix a rand() implementation which is deficient in this
  74. way.  A few months ago, sympathetic to the plight of the
  75. umpteenth programmer who had been bitten by this problem, I
  76. submitted a "formal" bug report to comp.bugs.4bsd, where I was
  77. met with the (barely) polite response that "everyone knows not to
  78. take rand() % N, so it's not a problem."  A classic case of
  79. blaming the victim, and of blaming the user for a software
  80. deficiency.
  81.  
  82. It's quite true that there are more ways to go astray with a
  83. pseudo-random number generator than to take the values of a
  84. poorly-written one modulo small powers of 2.  (You can also run
  85. into problems if your range is not small with respect to, and
  86. does not evenly divide, the period of the RNG.  [Note 2.])
  87. I happen to think that the rand() % N problem is so common, and is
  88. so easily made by the unwary, that it's worth fixing [note 3];
  89. but again, it doesn't matter what I think.  The deficient RNG's
  90. are out there, and they're out there to stay (never mind that
  91. we've known for decades how to write better ones), and cautious
  92. programmers mustn't take rand() % N.
  93.  
  94.                     Steve Summit
  95.                     scs@adam.mit.edu
  96.  
  97. Note 1.  Yes, I know about BSD's random().
  98.  
  99. Note 2.  There are more subtle problems which can arise when
  100. using RNG's; in fact, you can prove that for any pseudo-random
  101. number generator, no matter how "good" it is, there is an
  102. application for which it is seriously deficient if not useless.
  103. I don't recall the details of the proof off the top of my head,
  104. but here is an example which is suggestive.  Consider a very
  105. simple rand(), with a RAND_MAX of 7 and a period of 8, which
  106. returns on successive calls the numbers 0, 1, 4, 2, 7, 6, 3, 5,
  107. and then repeats.  (Looks pretty random, right?)  Consider a
  108. program which, for whatever reason, takes one value from rand(),
  109. then takes one value and discards one value (i.e. calls rand()
  110. and ignores the result), then takes one value and discards two
  111. values, then takes one and discards three, and so on until it has
  112. taken a value and discarded 6 values, at which point it takes one
  113. last value.  (Try it.)  This is a contrived example, but the
  114. point is that for any random number generator which ever repeats
  115. itself or has any hidden, underlying order (and all pseudo-random
  116. number have some hidden order somewhere, since they are
  117. deterministic processes), there exist calling sequences
  118. which will beat against the underlying order and produce strongly
  119. ordered output.
  120.  
  121. Note 3. You can argue that vendors do application programmers a
  122. favor by supplying rand()'s which are orderly in their low-order
  123. bits, so that the programmers immediately "fix" their code and
  124. are not lulled by a decent rand() into a false sense of security,
  125. only to have it dashed when the code is ported to a machine with
  126. a deficient version.  Sometimes I agree with this argument;
  127. somehow, in this case, I don't.  (There was an airline pilot who
  128. used to test new co-pilots by deliberately mis-setting some
  129. control shortly before takeoff; people weren't too happy when
  130. this practice was discovered.  I shouldn't mention this, because
  131. it'll probably cloud the issue, and I'm not even sure I disagree
  132. with the captain in question.)
  133.