summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_random.py
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2003-10-05 09:09:15 (GMT)
committerRaymond Hettinger <python@rcn.com>2003-10-05 09:09:15 (GMT)
commit2f726e9093381572b21edbfc42659ea89fbdf686 (patch)
tree9625e748344e1709fc69a8b98298efdd602b4cc2 /Lib/test/test_random.py
parent5c68ef04b7f0c0c1d342647a7db2d3f76637d3fa (diff)
downloadcpython-2f726e9093381572b21edbfc42659ea89fbdf686.zip
cpython-2f726e9093381572b21edbfc42659ea89fbdf686.tar.gz
cpython-2f726e9093381572b21edbfc42659ea89fbdf686.tar.bz2
SF bug #812202: randint is always even
* Added C coded getrandbits(k) method that runs in linear time. * Call the new method from randrange() for ranges >= 2**53. * Adds a warning for generators not defining getrandbits() whenever they have a call to randrange() with too large of a population.
Diffstat (limited to 'Lib/test/test_random.py')
-rw-r--r--Lib/test/test_random.py78
1 files changed, 78 insertions, 0 deletions
diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
index fbd4184..3796c3b 100644
--- a/Lib/test/test_random.py
+++ b/Lib/test/test_random.py
@@ -4,6 +4,7 @@ import unittest
import random
import time
import pickle
+import warnings
from math import log, exp, sqrt, pi
from sets import Set
from test import test_support
@@ -153,6 +154,13 @@ class WichmannHill_TestBasicOps(TestBasicOps):
self.assertEqual(x1, x2)
self.assertEqual(y1, y2)
+ def test_bigrand(self):
+ # Verify warnings are raised when randrange is too large for random()
+ oldfilters = warnings.filters[:]
+ warnings.filterwarnings("error", "Underlying random")
+ self.assertRaises(UserWarning, self.gen.randrange, 2**60)
+ warnings.filters[:] = oldfilters
+
class MersenneTwister_TestBasicOps(TestBasicOps):
gen = random.Random()
@@ -219,6 +227,76 @@ class MersenneTwister_TestBasicOps(TestBasicOps):
seed = (1L << (10000 * 8)) - 1 # about 10K bytes
self.gen.seed(seed)
+ def test_53_bits_per_float(self):
+ # This should pass whenever a C double has 53 bit precision.
+ span = 2 ** 53
+ cum = 0
+ for i in xrange(100):
+ cum |= int(self.gen.random() * span)
+ self.assertEqual(cum, span-1)
+
+ def test_bigrand(self):
+ # The randrange routine should build-up the required number of bits
+ # in stages so that all bit positions are active.
+ span = 2 ** 500
+ cum = 0
+ for i in xrange(100):
+ r = self.gen.randrange(span)
+ self.assert_(0 <= r < span)
+ cum |= r
+ self.assertEqual(cum, span-1)
+
+ def test_bigrand_ranges(self):
+ for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
+ start = self.gen.randrange(2 ** i)
+ stop = self.gen.randrange(2 ** (i-2))
+ if stop <= start:
+ return
+ self.assert_(start <= self.gen.randrange(start, stop) < stop)
+
+ def test_rangelimits(self):
+ for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
+ self.assertEqual(Set(range(start,stop)),
+ Set([self.gen.randrange(start,stop) for i in xrange(100)]))
+
+ def test_genrandbits(self):
+ # Verify cross-platform repeatability
+ self.gen.seed(1234567)
+ self.assertEqual(self.gen.getrandbits(100),
+ 97904845777343510404718956115L)
+ # Verify ranges
+ for k in xrange(1, 1000):
+ self.assert_(0 <= self.gen.getrandbits(k) < 2**k)
+
+ # Verify all bits active
+ getbits = self.gen.getrandbits
+ for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]:
+ cum = 0
+ for i in xrange(100):
+ cum |= getbits(span)
+ self.assertEqual(cum, 2**span-1)
+
+ def test_randbelow_logic(self, _log=log, int=int):
+ # check bitcount transition points: 2**i and 2**(i+1)-1
+ # show that: k = int(1.001 + _log(n, 2))
+ # is equal to or one greater than the number of bits in n
+ for i in xrange(1, 1000):
+ n = 1L << i # check an exact power of two
+ numbits = i+1
+ k = int(1.00001 + _log(n, 2))
+ self.assertEqual(k, numbits)
+ self.assert_(n == 2**(k-1))
+
+ n += n - 1 # check 1 below the next power of two
+ k = int(1.00001 + _log(n, 2))
+ self.assert_(k in [numbits, numbits+1])
+ self.assert_(2**k > n > 2**(k-2))
+
+ n -= n >> 15 # check a little farther below the next power of two
+ k = int(1.00001 + _log(n, 2))
+ self.assertEqual(k, numbits) # note the stronger assertion
+ self.assert_(2**k > n > 2**(k-1)) # note the stronger assertion
+
_gammacoeff = (0.9999999999995183, 676.5203681218835, -1259.139216722289,
771.3234287757674, -176.6150291498386, 12.50734324009056,
-0.1385710331296526, 0.9934937113930748e-05, 0.1659470187408462e-06)