home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Lib / whrandom.py < prev    next >
Text File  |  1997-07-10  |  2KB  |  97 lines

  1. #    WICHMANN-HILL RANDOM NUMBER GENERATOR
  2. #
  3. #    Wichmann, B. A. & Hill, I. D. (1982)
  4. #    Algorithm AS 183: 
  5. #    An efficient and portable pseudo-random number generator
  6. #    Applied Statistics 31 (1982) 188-190
  7. #
  8. #    see also: 
  9. #        Correction to Algorithm AS 183
  10. #        Applied Statistics 33 (1984) 123  
  11. #
  12. #        McLeod, A. I. (1985)
  13. #        A remark on Algorithm AS 183 
  14. #        Applied Statistics 34 (1985),198-200
  15. #
  16. #
  17. #    USE:
  18. #    whrandom.random()    yields double precision random numbers 
  19. #                uniformly distributed between 0 and 1.
  20. #
  21. #    whrandom.seed(x, y, z)    must be called before whrandom.random()
  22. #                to seed the generator
  23. #
  24. #    There is also an interface to create multiple independent
  25. #    random generators, and to choose from other ranges.
  26.  
  27.  
  28. #    Translated by Guido van Rossum from C source provided by
  29. #    Adrian Baddeley.
  30.  
  31.  
  32. class whrandom:
  33.     #
  34.     # Initialize an instance.
  35.     # Without arguments, initialize from current time.
  36.     # With arguments (x, y, z), initialize from them.
  37.     #
  38.     def __init__(self, x = 0, y = 0, z = 0):
  39.         self.seed(x, y, z)
  40.     #
  41.     # Set the seed from (x, y, z).
  42.     # These must be integers in the range [0, 256).
  43.     #
  44.     def seed(self, x = 0, y = 0, z = 0):
  45.         if not type(x) == type(y) == type(z) == type(0):
  46.             raise TypeError, 'seeds must be integers'
  47.         if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
  48.             raise ValueError, 'seeds must be in range(0, 256)'
  49.         if 0 == x == y == z:
  50.             # Initialize from current time
  51.             import time
  52.             t = long(time.time() * 256)
  53.             t = int((t&0xffffff) | (t>>24))
  54.             t, x = divmod(t, 256)
  55.             t, y = divmod(t, 256)
  56.             t, z = divmod(t, 256)
  57.         # Zero is a poor seed, so substitute 1
  58.         self._seed = (x or 1, y or 1, z or 1)
  59.     #
  60.     # Get the next random number in the range [0.0, 1.0).
  61.     #
  62.     def random(self):
  63.         x, y, z = self._seed
  64.         #
  65.         x = (171 * x) % 30269
  66.         y = (172 * y) % 30307
  67.         z = (170 * z) % 30323
  68.         #
  69.         self._seed = x, y, z
  70.         #
  71.         return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
  72.     #
  73.     # Get a random number in the range [a, b).
  74.     #
  75.     def uniform(self, a, b):
  76.         return a + (b-a) * self.random()
  77.     #
  78.     # Get a random integer in the range [a, b] including both end points.
  79.     #
  80.     def randint(self, a, b):
  81.         return a + int(self.random() * (b+1-a))
  82.     #
  83.     # Choose a random element from a non-empty sequence.
  84.     #
  85.     def choice(self, seq):
  86.         return seq[int(self.random() * len(seq))]
  87.  
  88.  
  89. # Initialize from the current time
  90. #
  91. _inst = whrandom()
  92. seed = _inst.seed
  93. random = _inst.random
  94. uniform = _inst.uniform
  95. randint = _inst.randint
  96. choice = _inst.choice
  97.