summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-02-01 04:59:18 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-02-01 04:59:18 (GMT)
commit0de88fc4b108751b86443852b6741680d704168f (patch)
treea3824b12e3ed7dc1d65667388a4ace86f7fffe6e /Lib
parent0eb107068a4a66d9c4df7276ca330b7d0312645e (diff)
downloadcpython-0de88fc4b108751b86443852b6741680d704168f.zip
cpython-0de88fc4b108751b86443852b6741680d704168f.tar.gz
cpython-0de88fc4b108751b86443852b6741680d704168f.tar.bz2
Change random.seed() so that it can get at the full range of possible
internal states. Put the old .seed() (which could only get at about the square root of the # of possibilities) under the new name .whseed(), for bit-level compatibility with older versions. This occurred to me while reviewing effbot's book (he found himself stumbling over .seed() more than once there ...).
Diffstat (limited to 'Lib')
-rw-r--r--Lib/random.py104
1 files changed, 67 insertions, 37 deletions
diff --git a/Lib/random.py b/Lib/random.py
index b9359e4..427b731 100644
--- a/Lib/random.py
+++ b/Lib/random.py
@@ -66,10 +66,10 @@ used to "move backward in time":
>>> g = Random(42) # arbitrary
>>> g.random()
-0.24855401895528142
+0.25420336316883324
>>> g.jumpahead(6953607871644L - 1) # move *back* one
>>> g.random()
-0.24855401895528142
+0.25420336316883324
"""
# XXX The docstring sucks.
@@ -119,26 +119,31 @@ class Random:
# different core generator should override the seed(), random(),
# getstate(), setstate() and jumpahead() methods.
- def __whseed(self, x=0, y=0, z=0):
- """Set the Wichmann-Hill seed from (x, y, z).
+ def seed(self, a=None):
+ """Initialize internal state from hashable object.
- These must be integers in the range [0, 256).
+ None or no argument seeds from current time.
+
+ If a is not None or an int or long, hash(a) is instead.
+
+ If a is an int or long, a is used directly. Distinct values between
+ 0 and 27814431486575L inclusive are guaranteed to yield distinct
+ internal states (this guarantee is specific to the default
+ Wichmann-Hill generator).
"""
- if not type(x) == type(y) == type(z) == type(0):
- raise TypeError('seeds must be integers')
- if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
- raise ValueError('seeds must be in range(0, 256)')
- if 0 == x == y == z:
+ if a is None:
# Initialize from current time
import time
- t = long(time.time()) * 256
- t = int((t&0xffffff) ^ (t>>24))
- t, x = divmod(t, 256)
- t, y = divmod(t, 256)
- t, z = divmod(t, 256)
- # Zero is a poor seed, so substitute 1
- self._seed = (x or 1, y or 1, z or 1)
+ a = long(time.time() * 256)
+
+ if type(a) not in (type(3), type(3L)):
+ a = hash(a)
+
+ a, x = divmod(a, 30268)
+ a, y = divmod(a, 30306)
+ a, z = divmod(a, 30322)
+ self._seed = int(x)+1, int(y)+1, int(z)+1
def random(self):
"""Get the next random number in the range [0.0, 1.0)."""
@@ -171,26 +176,6 @@ class Random:
# never return 0.0 (asserted by Tim; proof too long for a comment).
return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
- def seed(self, a=None):
- """Seed from hashable object's hash code.
-
- None or no argument seeds from current time. It is not guaranteed
- that objects with distinct hash codes lead to distinct internal
- states.
- """
-
- if a is None:
- self.__whseed()
- return
- a = hash(a)
- a, x = divmod(a, 256)
- a, y = divmod(a, 256)
- a, z = divmod(a, 256)
- x = (x + a) % 256 or 1
- y = (y + a) % 256 or 1
- z = (z + a) % 256 or 1
- self.__whseed(x, y, z)
-
def getstate(self):
"""Return internal state; can be passed to setstate() later."""
return self.VERSION, self._seed, self.gauss_next
@@ -227,6 +212,50 @@ class Random:
z = int(z * pow(170, n, 30323)) % 30323
self._seed = x, y, z
+ def __whseed(self, x=0, y=0, z=0):
+ """Set the Wichmann-Hill seed from (x, y, z).
+
+ These must be integers in the range [0, 256).
+ """
+
+ if not type(x) == type(y) == type(z) == type(0):
+ raise TypeError('seeds must be integers')
+ if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
+ raise ValueError('seeds must be in range(0, 256)')
+ if 0 == x == y == z:
+ # Initialize from current time
+ import time
+ t = long(time.time() * 256)
+ t = int((t&0xffffff) ^ (t>>24))
+ t, x = divmod(t, 256)
+ t, y = divmod(t, 256)
+ t, z = divmod(t, 256)
+ # Zero is a poor seed, so substitute 1
+ self._seed = (x or 1, y or 1, z or 1)
+
+ def whseed(self, a=None):
+ """Seed from hashable object's hash code.
+
+ None or no argument seeds from current time. It is not guaranteed
+ that objects with distinct hash codes lead to distinct internal
+ states.
+
+ This is obsolete, provided for compatibility with the seed routine
+ used prior to Python 2.1. Use the .seed() method instead.
+ """
+
+ if a is None:
+ self.__whseed()
+ return
+ a = hash(a)
+ a, x = divmod(a, 256)
+ a, y = divmod(a, 256)
+ a, z = divmod(a, 256)
+ x = (x + a) % 256 or 1
+ y = (y + a) % 256 or 1
+ z = (z + a) % 256 or 1
+ self.__whseed(x, y, z)
+
## ---- Methods below this point do not need to be overridden when
## ---- subclassing for the purpose of using a different core generator.
@@ -623,6 +652,7 @@ weibullvariate = _inst.weibullvariate
getstate = _inst.getstate
setstate = _inst.setstate
jumpahead = _inst.jumpahead
+whseed = _inst.whseed
if __name__ == '__main__':
_test()