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

378 statements  

1"""Random variable generators. 

2 

3 bytes 

4 ----- 

5 uniform bytes (values between 0 and 255) 

6 

7 integers 

8 -------- 

9 uniform within range 

10 

11 sequences 

12 --------- 

13 pick random element 

14 pick random sample 

15 pick weighted random sample 

16 generate random permutation 

17 

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 

29 

30 distributions on the circle (angles 0 to 2pi) 

31 --------------------------------------------- 

32 circular uniform 

33 von Mises 

34 

35General notes on the underlying Mersenne Twister core generator: 

36 

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. 

41 

42""" 

43 

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. 

47 

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 

58 

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 

65 

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] 

93 

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 

99 

100 

101class Random(_random.Random): 

102 """Random number generator base class used by bound module functions. 

103 

104 Used to instantiate instances of Random to get generators that don't 

105 share state. 

106 

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. 

112 

113 """ 

114 

115 VERSION = 3 # used by getstate/setstate 

116 

117 def __init__(self, x=None): 

118 """Initialize an instance. 

119 

120 Optional argument x controls seeding, as for Random.seed(). 

121 """ 

122 

123 self.seed(x) 

124 self.gauss_next = None 

125 

126 def seed(self, a=None, version=2): 

127 """Initialize internal state from a seed. 

128 

129 The only supported seed types are None, int, float, 

130 str, bytes, and bytearray. 

131 

132 None or no argument seeds from current time or from an operating 

133 system specific randomness source if available. 

134 

135 If *a* is an int, all bits are used. 

136 

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. 

141 

142 """ 

143 

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 

151 

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') 

157 

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) 

165 

166 super().seed(a) 

167 self.gauss_next = None 

168 

169 def getstate(self): 

170 """Return internal state; can be passed to setstate() later.""" 

171 return self.VERSION, super().getstate(), self.gauss_next 

172 

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)) 

194 

195 

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. 

199 

200 

201 ## -------------------- pickle support ------------------- 

202 

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() 

208 

209 def __setstate__(self, state): # for pickle 

210 self.setstate(state) 

211 

212 def __reduce__(self): 

213 return self.__class__, (), self.getstate() 

214 

215 

216 ## ---- internal support method for evenly distributed integers ---- 

217 

218 def __init_subclass__(cls, /, **kwargs): 

219 """Control how subclasses generate random integers. 

220 

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 """ 

226 

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 

237 

238 def _randbelow_with_getrandbits(self, n): 

239 "Return a random int in the range [0,n). Returns 0 if n==0." 

240 

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 

249 

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. 

252 

253 The implementation does not use getrandbits, but only random. 

254 """ 

255 

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 

270 

271 _randbelow = _randbelow_with_getrandbits 

272 

273 

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(). 

280 

281 

282 ## -------------------- bytes methods --------------------- 

283 

284 def randbytes(self, n): 

285 """Generate n random bytes.""" 

286 return self.getrandbits(n * 8).to_bytes(n, 'little') 

287 

288 

289 ## -------------------- integer methods ------------------- 

290 

291 def randrange(self, start, stop=None, step=1): 

292 """Choose a random item from range(start, stop[, step]). 

293 

294 This fixes the problem with randint() which includes the 

295 endpoint; in Python this is usually not what you want. 

296 

297 """ 

298 

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()") 

308 

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)) 

318 

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()") 

329 

330 if n <= 0: 

331 raise ValueError("empty range for randrange()") 

332 

333 return istart + istep * self._randbelow(n) 

334 

335 def randint(self, a, b): 

336 """Return random integer in range [a, b], including both end points. 

337 """ 

338 

339 return self.randrange(a, b+1) 

340 

341 

342 ## -------------------- sequence methods ------------------- 

343 

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))] 

348 

349 def shuffle(self, x, random=None): 

350 """Shuffle list x in place, and return None. 

351 

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. 

355 

356 """ 

357 

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] 

374 

375 def sample(self, population, k, *, counts=None): 

376 """Chooses k unique random elements from a population sequence or set. 

377 

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). 

383 

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. 

387 

388 Repeated elements can be specified one at a time or with the optional 

389 counts parameter. For example: 

390 

391 sample(['red', 'blue'], counts=[4, 2], k=5) 

392 

393 is equivalent to: 

394 

395 sample(['red', 'red', 'red', 'red', 'blue', 'blue'], k=5) 

396 

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: 

400 

401 sample(range(10000000), 60) 

402 

403 """ 

404 

405 # Sampling without replacement entails tracking either potential 

406 # selections (the pool) in a list or previous selections in a set. 

407 

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. 

414 

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. 

419 

420 # Memory requirements are kept to the smaller of a k-length 

421 # set or an n-length list. 

422 

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. 

427 

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 

473 

474 def choices(self, population, weights=None, *, cum_weights=None, k=1): 

475 """Return a k sized list of population elements chosen with replacement. 

476 

477 If the relative weights or cumulative weights are not specified, 

478 the selections are made with equal probability. 

479 

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)] 

508 

509 

510 ## -------------------- real-valued distributions ------------------- 

511 

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() 

515 

516 def triangular(self, low=0.0, high=1.0, mode=None): 

517 """Triangular distribution. 

518 

519 Continuous distribution bounded by given lower and upper limits, 

520 and having a given mode value in-between. 

521 

522 http://en.wikipedia.org/wiki/Triangular_distribution 

523 

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) 

535 

536 def normalvariate(self, mu, sigma): 

537 """Normal distribution. 

538 

539 mu is the mean, and sigma is the standard deviation. 

540 

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. 

546 

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 

556 

557 def gauss(self, mu, sigma): 

558 """Gaussian distribution. 

559 

560 mu is the mean, and sigma is the standard deviation. This is 

561 slightly faster than the normalvariate() function. 

562 

563 Not thread-safe without a lock around calls. 

564 

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) 

576 

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.) 

583 

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 

592 

593 return mu + z * sigma 

594 

595 def lognormvariate(self, mu, sigma): 

596 """Log normal distribution. 

597 

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. 

601 

602 """ 

603 return _exp(self.normalvariate(mu, sigma)) 

604 

605 def expovariate(self, lambd): 

606 """Exponential distribution. 

607 

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. 

613 

614 """ 

615 # lambd: rate lambd = 1/mean 

616 # ('lambda' is a Python reserved word) 

617 

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 

621 

622 def vonmisesvariate(self, mu, kappa): 

623 """Circular data distribution. 

624 

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. 

629 

630 """ 

631 # Based upon an algorithm published in: Fisher, N.I., 

632 # "Statistical Analysis of Circular Data", Cambridge 

633 # University Press, 1993. 

634 

635 # Thanks to Magnus Kessler for a correction to the 

636 # implementation of step 4. 

637 

638 random = self.random 

639 if kappa <= 1e-6: 

640 return TWOPI * random() 

641 

642 s = 0.5 / kappa 

643 r = s + _sqrt(1.0 + s * s) 

644 

645 while True: 

646 u1 = random() 

647 z = _cos(_pi * u1) 

648 

649 d = z / (r + z) 

650 u2 = random() 

651 if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d): 

652 break 

653 

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 

661 

662 return theta 

663 

664 def gammavariate(self, alpha, beta): 

665 """Gamma distribution. Not the gamma function! 

666 

667 Conditions on the parameters are alpha > 0 and beta > 0. 

668 

669 The probability distribution function is: 

670 

671 x ** (alpha - 1) * math.exp(-x / beta) 

672 pdf(x) = -------------------------------------- 

673 math.gamma(alpha) * beta ** alpha 

674 

675 """ 

676 # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2 

677 

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') 

682 

683 random = self.random 

684 if alpha > 1.0: 

685 

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 

689 

690 ainv = _sqrt(2.0 * alpha - 1.0) 

691 bbb = alpha - LOG4 

692 ccc = alpha + ainv 

693 

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 

705 

706 elif alpha == 1.0: 

707 # expovariate(1/beta) 

708 return -_log(1.0 - random()) * beta 

709 

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 

728 

729 def betavariate(self, alpha, beta): 

730 """Beta distribution. 

731 

732 Conditions on the parameters are alpha > 0 and beta > 0. 

733 Returned values range between 0 and 1. 

734 

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. 

748 

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 

755 

756 def paretovariate(self, alpha): 

757 """Pareto distribution. alpha is the shape parameter.""" 

758 # Jain, pg. 495 

759 

760 u = 1.0 - self.random() 

761 return 1.0 / u ** (1.0 / alpha) 

762 

763 def weibullvariate(self, alpha, beta): 

764 """Weibull distribution. 

765 

766 alpha is the scale parameter and beta is the shape parameter. 

767 

768 """ 

769 # Jain, pg. 499; bug fix courtesy Bill Arms 

770 

771 u = 1.0 - self.random() 

772 return alpha * (-_log(u)) ** (1.0 / beta) 

773 

774 

775## ------------------------------------------------------------------ 

776## --------------- Operating System Random Source ------------------ 

777 

778 

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). 

783 

784 Not available on all systems (see os.urandom() for details). 

785 

786 """ 

787 

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 

791 

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 

799 

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) 

805 

806 def seed(self, *args, **kwds): 

807 "Stub method. Not used for a system random number generator." 

808 return None 

809 

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 

814 

815 

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. 

822 

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 

847 

848 

849## ------------------------------------------------------ 

850## ----------------- test program ----------------------- 

851 

852def _test_generator(n, func, args): 

853 from statistics import stdev, fmean as mean 

854 from time import perf_counter 

855 

856 t0 = perf_counter() 

857 data = [func(*args) for i in range(n)] 

858 t1 = perf_counter() 

859 

860 xbar = mean(data) 

861 sigma = stdev(data, xbar) 

862 low = min(data) 

863 high = max(data) 

864 

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)) 

867 

868 

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)) 

886 

887 

888## ------------------------------------------------------ 

889## ------------------ fork support --------------------- 

890 

891if hasattr(_os, "fork"): 

892 _os.register_at_fork(after_in_child=_inst.seed) 

893 

894 

895if __name__ == '__main__': 

896 _test()