Coverage for /pythoncovmergedfiles/medio/medio/usr/lib/python3.9/random.py: 4%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Random variable generators.
3 bytes
4 -----
5 uniform bytes (values between 0 and 255)
7 integers
8 --------
9 uniform within range
11 sequences
12 ---------
13 pick random element
14 pick random sample
15 pick weighted random sample
16 generate random permutation
18 distributions on the real line:
19 ------------------------------
20 uniform
21 triangular
22 normal (Gaussian)
23 lognormal
24 negative exponential
25 gamma
26 beta
27 pareto
28 Weibull
30 distributions on the circle (angles 0 to 2pi)
31 ---------------------------------------------
32 circular uniform
33 von Mises
35General notes on the underlying Mersenne Twister core generator:
37* The period is 2**19937-1.
38* It is one of the most extensively tested generators in existence.
39* The random() method is implemented in C, executes in a single Python step,
40 and is, therefore, threadsafe.
42"""
44# Translated by Guido van Rossum from C source provided by
45# Adrian Baddeley. Adapted by Raymond Hettinger for use with
46# the Mersenne Twister and os.urandom() core generators.
48from warnings import warn as _warn
49from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
50from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
51from math import tau as TWOPI, floor as _floor
52from os import urandom as _urandom
53from _collections_abc import Set as _Set, Sequence as _Sequence
54from itertools import accumulate as _accumulate, repeat as _repeat
55from bisect import bisect as _bisect
56import os as _os
57import _random
59try:
60 # hashlib is pretty heavy to load, try lean internal module first
61 from _sha512 import sha512 as _sha512
62except ImportError:
63 # fallback to official implementation
64 from hashlib import sha512 as _sha512
66__all__ = [
67 "Random",
68 "SystemRandom",
69 "betavariate",
70 "choice",
71 "choices",
72 "expovariate",
73 "gammavariate",
74 "gauss",
75 "getrandbits",
76 "getstate",
77 "lognormvariate",
78 "normalvariate",
79 "paretovariate",
80 "randbytes",
81 "randint",
82 "random",
83 "randrange",
84 "sample",
85 "seed",
86 "setstate",
87 "shuffle",
88 "triangular",
89 "uniform",
90 "vonmisesvariate",
91 "weibullvariate",
92]
94NV_MAGICCONST = 4 * _exp(-0.5) / _sqrt(2.0)
95LOG4 = _log(4.0)
96SG_MAGICCONST = 1.0 + _log(4.5)
97BPF = 53 # Number of bits in a float
98RECIP_BPF = 2 ** -BPF
101class Random(_random.Random):
102 """Random number generator base class used by bound module functions.
104 Used to instantiate instances of Random to get generators that don't
105 share state.
107 Class Random can also be subclassed if you want to use a different basic
108 generator of your own devising: in that case, override the following
109 methods: random(), seed(), getstate(), and setstate().
110 Optionally, implement a getrandbits() method so that randrange()
111 can cover arbitrarily large ranges.
113 """
115 VERSION = 3 # used by getstate/setstate
117 def __init__(self, x=None):
118 """Initialize an instance.
120 Optional argument x controls seeding, as for Random.seed().
121 """
123 self.seed(x)
124 self.gauss_next = None
126 def seed(self, a=None, version=2):
127 """Initialize internal state from a seed.
129 The only supported seed types are None, int, float,
130 str, bytes, and bytearray.
132 None or no argument seeds from current time or from an operating
133 system specific randomness source if available.
135 If *a* is an int, all bits are used.
137 For version 2 (the default), all of the bits are used if *a* is a str,
138 bytes, or bytearray. For version 1 (provided for reproducing random
139 sequences from older versions of Python), the algorithm for str and
140 bytes generates a narrower range of seeds.
142 """
144 if version == 1 and isinstance(a, (str, bytes)):
145 a = a.decode('latin-1') if isinstance(a, bytes) else a
146 x = ord(a[0]) << 7 if a else 0
147 for c in map(ord, a):
148 x = ((1000003 * x) ^ c) & 0xFFFFFFFFFFFFFFFF
149 x ^= len(a)
150 a = -2 if x == -1 else x
152 elif version == 2 and isinstance(a, (str, bytes, bytearray)):
153 if isinstance(a, str):
154 a = a.encode()
155 a += _sha512(a).digest()
156 a = int.from_bytes(a, 'big')
158 elif not isinstance(a, (type(None), int, float, str, bytes, bytearray)):
159 _warn('Seeding based on hashing is deprecated\n'
160 'since Python 3.9 and will be removed in a subsequent '
161 'version. The only \n'
162 'supported seed types are: None, '
163 'int, float, str, bytes, and bytearray.',
164 DeprecationWarning, 2)
166 super().seed(a)
167 self.gauss_next = None
169 def getstate(self):
170 """Return internal state; can be passed to setstate() later."""
171 return self.VERSION, super().getstate(), self.gauss_next
173 def setstate(self, state):
174 """Restore internal state from object returned by getstate()."""
175 version = state[0]
176 if version == 3:
177 version, internalstate, self.gauss_next = state
178 super().setstate(internalstate)
179 elif version == 2:
180 version, internalstate, self.gauss_next = state
181 # In version 2, the state was saved as signed ints, which causes
182 # inconsistencies between 32/64-bit systems. The state is
183 # really unsigned 32-bit ints, so we convert negative ints from
184 # version 2 to positive longs for version 3.
185 try:
186 internalstate = tuple(x % (2 ** 32) for x in internalstate)
187 except ValueError as e:
188 raise TypeError from e
189 super().setstate(internalstate)
190 else:
191 raise ValueError("state with version %s passed to "
192 "Random.setstate() of version %s" %
193 (version, self.VERSION))
196 ## -------------------------------------------------------
197 ## ---- Methods below this point do not need to be overridden or extended
198 ## ---- when subclassing for the purpose of using a different core generator.
201 ## -------------------- pickle support -------------------
203 # Issue 17489: Since __reduce__ was defined to fix #759889 this is no
204 # longer called; we leave it here because it has been here since random was
205 # rewritten back in 2001 and why risk breaking something.
206 def __getstate__(self): # for pickle
207 return self.getstate()
209 def __setstate__(self, state): # for pickle
210 self.setstate(state)
212 def __reduce__(self):
213 return self.__class__, (), self.getstate()
216 ## ---- internal support method for evenly distributed integers ----
218 def __init_subclass__(cls, /, **kwargs):
219 """Control how subclasses generate random integers.
221 The algorithm a subclass can use depends on the random() and/or
222 getrandbits() implementation available to it and determines
223 whether it can generate random integers from arbitrarily large
224 ranges.
225 """
227 for c in cls.__mro__:
228 if '_randbelow' in c.__dict__:
229 # just inherit it
230 break
231 if 'getrandbits' in c.__dict__:
232 cls._randbelow = cls._randbelow_with_getrandbits
233 break
234 if 'random' in c.__dict__:
235 cls._randbelow = cls._randbelow_without_getrandbits
236 break
238 def _randbelow_with_getrandbits(self, n):
239 "Return a random int in the range [0,n). Returns 0 if n==0."
241 if not n:
242 return 0
243 getrandbits = self.getrandbits
244 k = n.bit_length() # don't use (n-1) here because n can be 1
245 r = getrandbits(k) # 0 <= r < 2**k
246 while r >= n:
247 r = getrandbits(k)
248 return r
250 def _randbelow_without_getrandbits(self, n, maxsize=1<<BPF):
251 """Return a random int in the range [0,n). Returns 0 if n==0.
253 The implementation does not use getrandbits, but only random.
254 """
256 random = self.random
257 if n >= maxsize:
258 _warn("Underlying random() generator does not supply \n"
259 "enough bits to choose from a population range this large.\n"
260 "To remove the range limitation, add a getrandbits() method.")
261 return _floor(random() * n)
262 if n == 0:
263 return 0
264 rem = maxsize % n
265 limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0
266 r = random()
267 while r >= limit:
268 r = random()
269 return _floor(r * maxsize) % n
271 _randbelow = _randbelow_with_getrandbits
274 ## --------------------------------------------------------
275 ## ---- Methods below this point generate custom distributions
276 ## ---- based on the methods defined above. They do not
277 ## ---- directly touch the underlying generator and only
278 ## ---- access randomness through the methods: random(),
279 ## ---- getrandbits(), or _randbelow().
282 ## -------------------- bytes methods ---------------------
284 def randbytes(self, n):
285 """Generate n random bytes."""
286 return self.getrandbits(n * 8).to_bytes(n, 'little')
289 ## -------------------- integer methods -------------------
291 def randrange(self, start, stop=None, step=1):
292 """Choose a random item from range(start, stop[, step]).
294 This fixes the problem with randint() which includes the
295 endpoint; in Python this is usually not what you want.
297 """
299 # This code is a bit messy to make it fast for the
300 # common case while still doing adequate error checking.
301 istart = int(start)
302 if istart != start:
303 raise ValueError("non-integer arg 1 for randrange()")
304 if stop is None:
305 if istart > 0:
306 return self._randbelow(istart)
307 raise ValueError("empty range for randrange()")
309 # stop argument supplied.
310 istop = int(stop)
311 if istop != stop:
312 raise ValueError("non-integer stop for randrange()")
313 width = istop - istart
314 if step == 1 and width > 0:
315 return istart + self._randbelow(width)
316 if step == 1:
317 raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
319 # Non-unit step argument supplied.
320 istep = int(step)
321 if istep != step:
322 raise ValueError("non-integer step for randrange()")
323 if istep > 0:
324 n = (width + istep - 1) // istep
325 elif istep < 0:
326 n = (width + istep + 1) // istep
327 else:
328 raise ValueError("zero step for randrange()")
330 if n <= 0:
331 raise ValueError("empty range for randrange()")
333 return istart + istep * self._randbelow(n)
335 def randint(self, a, b):
336 """Return random integer in range [a, b], including both end points.
337 """
339 return self.randrange(a, b+1)
342 ## -------------------- sequence methods -------------------
344 def choice(self, seq):
345 """Choose a random element from a non-empty sequence."""
346 # raises IndexError if seq is empty
347 return seq[self._randbelow(len(seq))]
349 def shuffle(self, x, random=None):
350 """Shuffle list x in place, and return None.
352 Optional argument random is a 0-argument function returning a
353 random float in [0.0, 1.0); if it is the default None, the
354 standard random.random will be used.
356 """
358 if random is None:
359 randbelow = self._randbelow
360 for i in reversed(range(1, len(x))):
361 # pick an element in x[:i+1] with which to exchange x[i]
362 j = randbelow(i + 1)
363 x[i], x[j] = x[j], x[i]
364 else:
365 _warn('The *random* parameter to shuffle() has been deprecated\n'
366 'since Python 3.9 and will be removed in a subsequent '
367 'version.',
368 DeprecationWarning, 2)
369 floor = _floor
370 for i in reversed(range(1, len(x))):
371 # pick an element in x[:i+1] with which to exchange x[i]
372 j = floor(random() * (i + 1))
373 x[i], x[j] = x[j], x[i]
375 def sample(self, population, k, *, counts=None):
376 """Chooses k unique random elements from a population sequence or set.
378 Returns a new list containing elements from the population while
379 leaving the original population unchanged. The resulting list is
380 in selection order so that all sub-slices will also be valid random
381 samples. This allows raffle winners (the sample) to be partitioned
382 into grand prize and second place winners (the subslices).
384 Members of the population need not be hashable or unique. If the
385 population contains repeats, then each occurrence is a possible
386 selection in the sample.
388 Repeated elements can be specified one at a time or with the optional
389 counts parameter. For example:
391 sample(['red', 'blue'], counts=[4, 2], k=5)
393 is equivalent to:
395 sample(['red', 'red', 'red', 'red', 'blue', 'blue'], k=5)
397 To choose a sample from a range of integers, use range() for the
398 population argument. This is especially fast and space efficient
399 for sampling from a large population:
401 sample(range(10000000), 60)
403 """
405 # Sampling without replacement entails tracking either potential
406 # selections (the pool) in a list or previous selections in a set.
408 # When the number of selections is small compared to the
409 # population, then tracking selections is efficient, requiring
410 # only a small set and an occasional reselection. For
411 # a larger number of selections, the pool tracking method is
412 # preferred since the list takes less space than the
413 # set and it doesn't suffer from frequent reselections.
415 # The number of calls to _randbelow() is kept at or near k, the
416 # theoretical minimum. This is important because running time
417 # is dominated by _randbelow() and because it extracts the
418 # least entropy from the underlying random number generators.
420 # Memory requirements are kept to the smaller of a k-length
421 # set or an n-length list.
423 # There are other sampling algorithms that do not require
424 # auxiliary memory, but they were rejected because they made
425 # too many calls to _randbelow(), making them slower and
426 # causing them to eat more entropy than necessary.
428 if isinstance(population, _Set):
429 _warn('Sampling from a set deprecated\n'
430 'since Python 3.9 and will be removed in a subsequent version.',
431 DeprecationWarning, 2)
432 population = tuple(population)
433 if not isinstance(population, _Sequence):
434 raise TypeError("Population must be a sequence. For dicts or sets, use sorted(d).")
435 n = len(population)
436 if counts is not None:
437 cum_counts = list(_accumulate(counts))
438 if len(cum_counts) != n:
439 raise ValueError('The number of counts does not match the population')
440 total = cum_counts.pop()
441 if not isinstance(total, int):
442 raise TypeError('Counts must be integers')
443 if total <= 0:
444 raise ValueError('Total of counts must be greater than zero')
445 selections = self.sample(range(total), k=k)
446 bisect = _bisect
447 return [population[bisect(cum_counts, s)] for s in selections]
448 randbelow = self._randbelow
449 if not 0 <= k <= n:
450 raise ValueError("Sample larger than population or is negative")
451 result = [None] * k
452 setsize = 21 # size of a small set minus size of an empty list
453 if k > 5:
454 setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets
455 if n <= setsize:
456 # An n-length list is smaller than a k-length set.
457 # Invariant: non-selected at pool[0 : n-i]
458 pool = list(population)
459 for i in range(k):
460 j = randbelow(n - i)
461 result[i] = pool[j]
462 pool[j] = pool[n - i - 1] # move non-selected item into vacancy
463 else:
464 selected = set()
465 selected_add = selected.add
466 for i in range(k):
467 j = randbelow(n)
468 while j in selected:
469 j = randbelow(n)
470 selected_add(j)
471 result[i] = population[j]
472 return result
474 def choices(self, population, weights=None, *, cum_weights=None, k=1):
475 """Return a k sized list of population elements chosen with replacement.
477 If the relative weights or cumulative weights are not specified,
478 the selections are made with equal probability.
480 """
481 random = self.random
482 n = len(population)
483 if cum_weights is None:
484 if weights is None:
485 floor = _floor
486 n += 0.0 # convert to float for a small speed improvement
487 return [population[floor(random() * n)] for i in _repeat(None, k)]
488 try:
489 cum_weights = list(_accumulate(weights))
490 except TypeError:
491 if not isinstance(weights, int):
492 raise
493 k = weights
494 raise TypeError(
495 f'The number of choices must be a keyword argument: {k=}'
496 ) from None
497 elif weights is not None:
498 raise TypeError('Cannot specify both weights and cumulative weights')
499 if len(cum_weights) != n:
500 raise ValueError('The number of weights does not match the population')
501 total = cum_weights[-1] + 0.0 # convert to float
502 if total <= 0.0:
503 raise ValueError('Total of weights must be greater than zero')
504 bisect = _bisect
505 hi = n - 1
506 return [population[bisect(cum_weights, random() * total, 0, hi)]
507 for i in _repeat(None, k)]
510 ## -------------------- real-valued distributions -------------------
512 def uniform(self, a, b):
513 "Get a random number in the range [a, b) or [a, b] depending on rounding."
514 return a + (b - a) * self.random()
516 def triangular(self, low=0.0, high=1.0, mode=None):
517 """Triangular distribution.
519 Continuous distribution bounded by given lower and upper limits,
520 and having a given mode value in-between.
522 http://en.wikipedia.org/wiki/Triangular_distribution
524 """
525 u = self.random()
526 try:
527 c = 0.5 if mode is None else (mode - low) / (high - low)
528 except ZeroDivisionError:
529 return low
530 if u > c:
531 u = 1.0 - u
532 c = 1.0 - c
533 low, high = high, low
534 return low + (high - low) * _sqrt(u * c)
536 def normalvariate(self, mu, sigma):
537 """Normal distribution.
539 mu is the mean, and sigma is the standard deviation.
541 """
542 # Uses Kinderman and Monahan method. Reference: Kinderman,
543 # A.J. and Monahan, J.F., "Computer generation of random
544 # variables using the ratio of uniform deviates", ACM Trans
545 # Math Software, 3, (1977), pp257-260.
547 random = self.random
548 while True:
549 u1 = random()
550 u2 = 1.0 - random()
551 z = NV_MAGICCONST * (u1 - 0.5) / u2
552 zz = z * z / 4.0
553 if zz <= -_log(u2):
554 break
555 return mu + z * sigma
557 def gauss(self, mu, sigma):
558 """Gaussian distribution.
560 mu is the mean, and sigma is the standard deviation. This is
561 slightly faster than the normalvariate() function.
563 Not thread-safe without a lock around calls.
565 """
566 # When x and y are two variables from [0, 1), uniformly
567 # distributed, then
568 #
569 # cos(2*pi*x)*sqrt(-2*log(1-y))
570 # sin(2*pi*x)*sqrt(-2*log(1-y))
571 #
572 # are two *independent* variables with normal distribution
573 # (mu = 0, sigma = 1).
574 # (Lambert Meertens)
575 # (corrected version; bug discovered by Mike Miller, fixed by LM)
577 # Multithreading note: When two threads call this function
578 # simultaneously, it is possible that they will receive the
579 # same return value. The window is very small though. To
580 # avoid this, you have to use a lock around all calls. (I
581 # didn't want to slow this down in the serial case by using a
582 # lock here.)
584 random = self.random
585 z = self.gauss_next
586 self.gauss_next = None
587 if z is None:
588 x2pi = random() * TWOPI
589 g2rad = _sqrt(-2.0 * _log(1.0 - random()))
590 z = _cos(x2pi) * g2rad
591 self.gauss_next = _sin(x2pi) * g2rad
593 return mu + z * sigma
595 def lognormvariate(self, mu, sigma):
596 """Log normal distribution.
598 If you take the natural logarithm of this distribution, you'll get a
599 normal distribution with mean mu and standard deviation sigma.
600 mu can have any value, and sigma must be greater than zero.
602 """
603 return _exp(self.normalvariate(mu, sigma))
605 def expovariate(self, lambd):
606 """Exponential distribution.
608 lambd is 1.0 divided by the desired mean. It should be
609 nonzero. (The parameter would be called "lambda", but that is
610 a reserved word in Python.) Returned values range from 0 to
611 positive infinity if lambd is positive, and from negative
612 infinity to 0 if lambd is negative.
614 """
615 # lambd: rate lambd = 1/mean
616 # ('lambda' is a Python reserved word)
618 # we use 1-random() instead of random() to preclude the
619 # possibility of taking the log of zero.
620 return -_log(1.0 - self.random()) / lambd
622 def vonmisesvariate(self, mu, kappa):
623 """Circular data distribution.
625 mu is the mean angle, expressed in radians between 0 and 2*pi, and
626 kappa is the concentration parameter, which must be greater than or
627 equal to zero. If kappa is equal to zero, this distribution reduces
628 to a uniform random angle over the range 0 to 2*pi.
630 """
631 # Based upon an algorithm published in: Fisher, N.I.,
632 # "Statistical Analysis of Circular Data", Cambridge
633 # University Press, 1993.
635 # Thanks to Magnus Kessler for a correction to the
636 # implementation of step 4.
638 random = self.random
639 if kappa <= 1e-6:
640 return TWOPI * random()
642 s = 0.5 / kappa
643 r = s + _sqrt(1.0 + s * s)
645 while True:
646 u1 = random()
647 z = _cos(_pi * u1)
649 d = z / (r + z)
650 u2 = random()
651 if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d):
652 break
654 q = 1.0 / r
655 f = (q + z) / (1.0 + q * z)
656 u3 = random()
657 if u3 > 0.5:
658 theta = (mu + _acos(f)) % TWOPI
659 else:
660 theta = (mu - _acos(f)) % TWOPI
662 return theta
664 def gammavariate(self, alpha, beta):
665 """Gamma distribution. Not the gamma function!
667 Conditions on the parameters are alpha > 0 and beta > 0.
669 The probability distribution function is:
671 x ** (alpha - 1) * math.exp(-x / beta)
672 pdf(x) = --------------------------------------
673 math.gamma(alpha) * beta ** alpha
675 """
676 # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
678 # Warning: a few older sources define the gamma distribution in terms
679 # of alpha > -1.0
680 if alpha <= 0.0 or beta <= 0.0:
681 raise ValueError('gammavariate: alpha and beta must be > 0.0')
683 random = self.random
684 if alpha > 1.0:
686 # Uses R.C.H. Cheng, "The generation of Gamma
687 # variables with non-integral shape parameters",
688 # Applied Statistics, (1977), 26, No. 1, p71-74
690 ainv = _sqrt(2.0 * alpha - 1.0)
691 bbb = alpha - LOG4
692 ccc = alpha + ainv
694 while 1:
695 u1 = random()
696 if not 1e-7 < u1 < 0.9999999:
697 continue
698 u2 = 1.0 - random()
699 v = _log(u1 / (1.0 - u1)) / ainv
700 x = alpha * _exp(v)
701 z = u1 * u1 * u2
702 r = bbb + ccc * v - x
703 if r + SG_MAGICCONST - 4.5 * z >= 0.0 or r >= _log(z):
704 return x * beta
706 elif alpha == 1.0:
707 # expovariate(1/beta)
708 return -_log(1.0 - random()) * beta
710 else:
711 # alpha is between 0 and 1 (exclusive)
712 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
713 while True:
714 u = random()
715 b = (_e + alpha) / _e
716 p = b * u
717 if p <= 1.0:
718 x = p ** (1.0 / alpha)
719 else:
720 x = -_log((b - p) / alpha)
721 u1 = random()
722 if p > 1.0:
723 if u1 <= x ** (alpha - 1.0):
724 break
725 elif u1 <= _exp(-x):
726 break
727 return x * beta
729 def betavariate(self, alpha, beta):
730 """Beta distribution.
732 Conditions on the parameters are alpha > 0 and beta > 0.
733 Returned values range between 0 and 1.
735 """
736 ## See
737 ## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html
738 ## for Ivan Frohne's insightful analysis of why the original implementation:
739 ##
740 ## def betavariate(self, alpha, beta):
741 ## # Discrete Event Simulation in C, pp 87-88.
742 ##
743 ## y = self.expovariate(alpha)
744 ## z = self.expovariate(1.0/beta)
745 ## return z/(y+z)
746 ##
747 ## was dead wrong, and how it probably got that way.
749 # This version due to Janne Sinkkonen, and matches all the std
750 # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
751 y = self.gammavariate(alpha, 1.0)
752 if y:
753 return y / (y + self.gammavariate(beta, 1.0))
754 return 0.0
756 def paretovariate(self, alpha):
757 """Pareto distribution. alpha is the shape parameter."""
758 # Jain, pg. 495
760 u = 1.0 - self.random()
761 return 1.0 / u ** (1.0 / alpha)
763 def weibullvariate(self, alpha, beta):
764 """Weibull distribution.
766 alpha is the scale parameter and beta is the shape parameter.
768 """
769 # Jain, pg. 499; bug fix courtesy Bill Arms
771 u = 1.0 - self.random()
772 return alpha * (-_log(u)) ** (1.0 / beta)
775## ------------------------------------------------------------------
776## --------------- Operating System Random Source ------------------
779class SystemRandom(Random):
780 """Alternate random number generator using sources provided
781 by the operating system (such as /dev/urandom on Unix or
782 CryptGenRandom on Windows).
784 Not available on all systems (see os.urandom() for details).
786 """
788 def random(self):
789 """Get the next random number in the range [0.0, 1.0)."""
790 return (int.from_bytes(_urandom(7), 'big') >> 3) * RECIP_BPF
792 def getrandbits(self, k):
793 """getrandbits(k) -> x. Generates an int with k random bits."""
794 if k < 0:
795 raise ValueError('number of bits must be non-negative')
796 numbytes = (k + 7) // 8 # bits / 8 and rounded up
797 x = int.from_bytes(_urandom(numbytes), 'big')
798 return x >> (numbytes * 8 - k) # trim excess bits
800 def randbytes(self, n):
801 """Generate n random bytes."""
802 # os.urandom(n) fails with ValueError for n < 0
803 # and returns an empty bytes string for n == 0.
804 return _urandom(n)
806 def seed(self, *args, **kwds):
807 "Stub method. Not used for a system random number generator."
808 return None
810 def _notimplemented(self, *args, **kwds):
811 "Method should not be called for a system random number generator."
812 raise NotImplementedError('System entropy source does not have state.')
813 getstate = setstate = _notimplemented
816# ----------------------------------------------------------------------
817# Create one instance, seeded from current time, and export its methods
818# as module-level functions. The functions share state across all uses
819# (both in the user's code and in the Python libraries), but that's fine
820# for most programs and is easier for the casual user than making them
821# instantiate their own Random() instance.
823_inst = Random()
824seed = _inst.seed
825random = _inst.random
826uniform = _inst.uniform
827triangular = _inst.triangular
828randint = _inst.randint
829choice = _inst.choice
830randrange = _inst.randrange
831sample = _inst.sample
832shuffle = _inst.shuffle
833choices = _inst.choices
834normalvariate = _inst.normalvariate
835lognormvariate = _inst.lognormvariate
836expovariate = _inst.expovariate
837vonmisesvariate = _inst.vonmisesvariate
838gammavariate = _inst.gammavariate
839gauss = _inst.gauss
840betavariate = _inst.betavariate
841paretovariate = _inst.paretovariate
842weibullvariate = _inst.weibullvariate
843getstate = _inst.getstate
844setstate = _inst.setstate
845getrandbits = _inst.getrandbits
846randbytes = _inst.randbytes
849## ------------------------------------------------------
850## ----------------- test program -----------------------
852def _test_generator(n, func, args):
853 from statistics import stdev, fmean as mean
854 from time import perf_counter
856 t0 = perf_counter()
857 data = [func(*args) for i in range(n)]
858 t1 = perf_counter()
860 xbar = mean(data)
861 sigma = stdev(data, xbar)
862 low = min(data)
863 high = max(data)
865 print(f'{t1 - t0:.3f} sec, {n} times {func.__name__}')
866 print('avg %g, stddev %g, min %g, max %g\n' % (xbar, sigma, low, high))
869def _test(N=2000):
870 _test_generator(N, random, ())
871 _test_generator(N, normalvariate, (0.0, 1.0))
872 _test_generator(N, lognormvariate, (0.0, 1.0))
873 _test_generator(N, vonmisesvariate, (0.0, 1.0))
874 _test_generator(N, gammavariate, (0.01, 1.0))
875 _test_generator(N, gammavariate, (0.1, 1.0))
876 _test_generator(N, gammavariate, (0.1, 2.0))
877 _test_generator(N, gammavariate, (0.5, 1.0))
878 _test_generator(N, gammavariate, (0.9, 1.0))
879 _test_generator(N, gammavariate, (1.0, 1.0))
880 _test_generator(N, gammavariate, (2.0, 1.0))
881 _test_generator(N, gammavariate, (20.0, 1.0))
882 _test_generator(N, gammavariate, (200.0, 1.0))
883 _test_generator(N, gauss, (0.0, 1.0))
884 _test_generator(N, betavariate, (3.0, 3.0))
885 _test_generator(N, triangular, (0.0, 1.0, 1.0 / 3.0))
888## ------------------------------------------------------
889## ------------------ fork support ---------------------
891if hasattr(_os, "fork"):
892 _os.register_at_fork(after_in_child=_inst.seed)
895if __name__ == '__main__':
896 _test()