summaryrefslogtreecommitdiff
path: root/Doc/library/random.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/library/random.rst')
-rw-r--r--Doc/library/random.rst67
1 files changed, 62 insertions, 5 deletions
diff --git a/Doc/library/random.rst b/Doc/library/random.rst
index 4e97b1dbad..5a9359484d 100644
--- a/Doc/library/random.rst
+++ b/Doc/library/random.rst
@@ -57,7 +57,7 @@ from sources provided by the operating system.
`Complementary-Multiply-with-Carry recipe
- <https://github.com/ActiveState/code/tree/master/recipes/Python/576707_Long_period_random_number/recipe-576707.py>`_ for a compatible alternative
+ <https://code.activestate.com/recipes/576707/>`_ for a compatible alternative
random number generator with a long period and comparatively simple update
operations.
@@ -180,8 +180,8 @@ Functions for sequences
The *weights* or *cum_weights* can use any numeric type that interoperates
with the :class:`float` values returned by :func:`random` (that includes
- integers, floats, and fractions but excludes decimals). Behavior is
- undefined if any weight is negative. A :exc:`ValueError` is raised if all
+ integers, floats, and fractions but excludes decimals). Weights are assumed
+ to be non-negative and finite. A :exc:`ValueError` is raised if all
weights are zero.
For a given seed, the :func:`choices` function with equal weighting
@@ -253,6 +253,8 @@ Functions for sequences
order so that the sample is reproducible.
+.. _real-valued-distributions:
+
Real-valued distributions
-------------------------
@@ -391,8 +393,8 @@ change across Python versions, but two aspects are guaranteed not to change:
.. _random-examples:
-Examples and Recipes
---------------------
+Examples
+--------
Basic examples::
@@ -536,3 +538,58 @@ Simulation of arrival times and service deliveries for a multiserver queue::
a tutorial by `Peter Norvig <http://norvig.com/bio.html>`_ covering
the basics of probability theory, how to write simulations, and
how to perform data analysis using Python.
+
+
+Recipes
+-------
+
+The default :func:`.random` returns multiples of 2⁻⁵³ in the range
+*0.0 ≤ x < 1.0*. All such numbers are evenly spaced and are exactly
+representable as Python floats. However, many other representable
+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. 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 :ref:`real valued distributions <real-valued-distributions>`
+in the class will use the new method::
+
+ >>> fr = FullRandom()
+ >>> fr.random()
+ 0.05954861408025609
+ >>> fr.expovariate(0.25)
+ 8.87925541791544
+
+The recipe is conceptually equivalent to an algorithm that chooses from
+all the multiples of 2⁻¹⁰⁷⁴ in the range *0.0 ≤ x < 1.0*. All such
+numbers are evenly spaced, but most have to be rounded down to the
+nearest representable Python float. (The value 2⁻¹⁰⁷⁴ is the smallest
+positive unnormalized float and is equal to ``math.ulp(0.0)``.)
+
+
+.. seealso::
+
+ `Generating Pseudo-random Floating-Point Values
+ <https://allendowney.com/research/rand/downey07randfloat.pdf>`_ a
+ paper by Allen B. Downey describing ways to generate more
+ fine-grained floats than normally generated by :func:`.random`.