home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Lib / whrandom.py < prev    next >
Text File  |  1993-12-29  |  3KB  |  105 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, *xyz):
  39.         if not xyz:
  40.             # Initialize from current time
  41.             import time
  42.             t = int(time.time())
  43.             t, x = divmod(t, 256)
  44.             t, y = divmod(t, 256)
  45.             t, z = divmod(t, 256)
  46.         else:
  47.             # Initialize from arguments (x, y, z)
  48.             x, y, z = xyz
  49.         self.seed(x, y, z)
  50.     #
  51.     # Set the seed from (x, y, z).
  52.     # These must be integers in the range [0, 256).
  53.     #
  54.     def seed(self, *xyz):
  55.         if type(xyz) <> type(()) or len(xyz) <> 3:
  56.             raise TypeError, '3 seeds required'
  57.         x, y, z = xyz
  58.         if not type(x) == type(y) == type(z) == type(0):
  59.             raise TypeError, 'seeds must be integers'
  60.         if not 0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256:
  61.             raise ValueError, 'seeds must be in range(0, 256)'
  62.         self._seed = xyz
  63.     #
  64.     # Get the next random number in the range [0.0, 1.0).
  65.     #
  66.     def random(self):
  67.         x, y, z = self._seed
  68.         #
  69.         x1, x2 = divmod(x, 177)
  70.         y1, y2 = divmod(y, 176)
  71.         z1, z2 = divmod(z, 178)
  72.         #
  73.         x = (171 * x2 -  2 * x1) % 30269
  74.         y = (172 * y2 - 35 * y1) % 30307
  75.         z = (170 * z2 - 63 * z1) % 30323
  76.         #
  77.         self._seed = x, y, z
  78.         #
  79.         return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
  80.     #
  81.     # Get a random number in the range [a, b).
  82.     #
  83.     def uniform(self, a, b):
  84.         return a + (b-a) * self.random()
  85.     #
  86.     # Get a random integer in the range [a, b] including both end points.
  87.     #
  88.     def randint(self, a, b):
  89.         return a + int(self.random() * (b+1-a))
  90.     #
  91.     # Choose a random element from a non-empty sequence.
  92.     #
  93.     def choice(self, seq):
  94.         return seq[int(self.random() * len(seq))]
  95.  
  96.  
  97. # Initialize from the current time
  98. #
  99. _inst = whrandom()
  100. seed = _inst.seed
  101. random = _inst.random
  102. uniform = _inst.uniform
  103. randint = _inst.randint
  104. choice = _inst.choice
  105.