diff --git a/Doc/library/random.rst b/Doc/library/random.rst index af5131df280..c19a8e0a7cb 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -391,8 +391,8 @@ change across Python versions, but two aspects are guaranteed not to change: .. _random-examples: -Examples and Recipes --------------------- +Examples +-------- Basic examples:: @@ -516,6 +516,52 @@ Simulation of arrival times and service deliveries for a multiserver queue:: print(f'Mean wait: {mean(waits):.1f} Max wait: {max(waits):.1f}') print('Quartiles:', [round(q, 1) for q in quantiles(waits)]) +Recipes +------- + +The default :func:`.random` returns multiples of 2⁻⁵³ in the range +*0.0 ≤ x < 1.0*. All such numbers are evenly spaced and exactly +representable as Python floats. However, many floats in that interval +are not possible selections. For example, ``0.05954861408025609`` +isn't an integer multiple of 2⁻⁵³. + +The following recipe takes a different approach. All floats in the +interval are possible selections. Conceptually it works by choosing +from evenly spaced multiples of 2⁻¹⁰⁷⁴ and then rounding down to the +nearest representable float. + +For efficiency, the actual mechanics involve calling +:func:`~math.ldexp` to construct a representable float. The mantissa +comes from a uniform distribution of integers in the range *2⁵² ≤ +mantissa < 2⁵³*. The exponent comes from a geometric distribution +where exponents smaller than *-53* occur half as often as the next +larger exponent. + +:: + + from random import Random + from math import ldexp + + class FullRandom(Random): + + def random(self): + mantissa = 0x10_0000_0000_0000 | self.getrandbits(52) + exponent = -53 + x = 0 + while not x: + x = self.getrandbits(32) + exponent += x.bit_length() - 32 + return ldexp(mantissa, exponent) + +All of the real valued distributions will use the new method:: + + >>> fr = FullRandom() + >>> fr.random() + 0.05954861408025609 + >>> fr.expovariate(0.25) + 8.87925541791544 + + .. seealso:: `Statistics for Hackers `_ @@ -536,3 +582,8 @@ Simulation of arrival times and service deliveries for a multiserver queue:: a tutorial by `Peter Norvig `_ covering the basics of probability theory, how to write simulations, and how to perform data analysis using Python. + + `Generating Pseudo-random Floating-Point Values + `_ a + paper by Allen B. Downey describing ways to generate more + fine-grained floats than normally generated by :func:`.random`.