summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2002-05-05 20:40:00 (GMT)
committerTim Peters <tim.peters@gmail.com>2002-05-05 20:40:00 (GMT)
commit46c04e140cf26d1b44935c28c6f15ea467400d22 (patch)
tree1b3adac92e00f74e196857c7289bce4f06929704
parent2b41b0d6a70330153952477baec47ec8c2efdc18 (diff)
downloadcpython-46c04e140cf26d1b44935c28c6f15ea467400d22.zip
cpython-46c04e140cf26d1b44935c28c6f15ea467400d22.tar.gz
cpython-46c04e140cf26d1b44935c28c6f15ea467400d22.tar.bz2
random.gauss() uses a piece of hidden state used by nothing else,
and the .seed() and .whseed() methods failed to reset it. In other words, setting the seed didn't completely determine the sequence of results produced by random.gauss(). It does now. Programs repeatedly mixing calls to a seed method with calls to gauss() may see different results now. Bugfix candidate (random.gauss() has always been broken in this way), despite that it may change results.
-rw-r--r--Lib/random.py5
-rw-r--r--Lib/test/test_random.py19
-rw-r--r--Misc/NEWS7
3 files changed, 30 insertions, 1 deletions
diff --git a/Lib/random.py b/Lib/random.py
index f502d1d..fe25642 100644
--- a/Lib/random.py
+++ b/Lib/random.py
@@ -116,7 +116,6 @@ class Random:
"""
self.seed(x)
- self.gauss_next = None
## -------------------- core generator -------------------
@@ -150,6 +149,8 @@ class Random:
a, z = divmod(a, 30322)
self._seed = int(x)+1, int(y)+1, int(z)+1
+ self.gauss_next = None
+
def random(self):
"""Get the next random number in the range [0.0, 1.0)."""
@@ -238,6 +239,8 @@ class Random:
# Zero is a poor seed, so substitute 1
self._seed = (x or 1, y or 1, z or 1)
+ self.gauss_next = None
+
def whseed(self, a=None):
"""Seed from hashable object's hash code.
diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
new file mode 100644
index 0000000..d508c9f
--- /dev/null
+++ b/Lib/test/test_random.py
@@ -0,0 +1,19 @@
+import test_support
+import random
+
+# Ensure that the seed() method initializes all the hidden state. In
+# particular, through 2.2.1 it failed to reset a piece of state used by
+# (and only by) the .gauss() method.
+
+for seed in 1, 12, 123, 1234, 12345, 123456, 654321:
+ for seeder in random.seed, random.whseed:
+ seeder(seed)
+ x1 = random.random()
+ y1 = random.gauss(0, 1)
+
+ seeder(seed)
+ x2 = random.random()
+ y2 = random.gauss(0, 1)
+
+ test_support.vereq(x1, x2)
+ test_support.vereq(y1, y2)
diff --git a/Misc/NEWS b/Misc/NEWS
index 2fb6a83..803287e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -104,6 +104,13 @@ Extension modules
Library
+- random.gauss() uses a piece of hidden state used by nothing else,
+ and the .seed() and .whseed() methods failed to reset it. In other
+ words, setting the seed didn't completely determine the sequence of
+ results produced by random.gauss(). It does now. Programs repeatedly
+ mixing calls to a seed method with calls to gauss() may see different
+ results now.
+
- The pickle.Pickler class grew a clear_memo() method to mimic that
provided by cPickle.Pickler.