[Python-checkins] python/dist/src/Lib random.py,1.51.8.3,1.51.8.4
rhettinger at users.sourceforge.net
rhettinger at users.sourceforge.net
Sun Oct 5 19:35:40 EDT 2003
Update of /cvsroot/python/python/dist/src/Lib
In directory sc8-pr-cvs1:/tmp/cvs-serv17515/Lib
Modified Files:
Tag: release23-maint
random.py
Log Message:
SF bug #812202: randint is always even
* Extend rangrange() to return meaningful results when the range is
larger than 2**53. Only applies to the MersenneTwister. WichmannHill
was left alone in the absence of a proof showing how multiple calls
could be combined to produce long bit streams.
* WichmannHill was missing from __all__.
Index: random.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/random.py,v
retrieving revision 1.51.8.3
retrieving revision 1.51.8.4
diff -C2 -d -r1.51.8.3 -r1.51.8.4
*** random.py 8 Sep 2003 19:15:43 -0000 1.51.8.3
--- random.py 5 Oct 2003 23:35:38 -0000 1.51.8.4
***************
*** 39,43 ****
"""
!
from math import log as _log, exp as _exp, pi as _pi, e as _e
from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
--- 39,43 ----
"""
! from types import BuiltinMethodType as _BuiltinMethodType
from math import log as _log, exp as _exp, pi as _pi, e as _e
from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
***************
*** 48,52 ****
"cunifvariate","expovariate","vonmisesvariate","gammavariate",
"stdgamma","gauss","betavariate","paretovariate","weibullvariate",
! "getstate","setstate","jumpahead"]
NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
--- 48,52 ----
"cunifvariate","expovariate","vonmisesvariate","gammavariate",
"stdgamma","gauss","betavariate","paretovariate","weibullvariate",
! "getstate","setstate","jumpahead", "WichmannHill"]
NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
***************
*** 54,57 ****
--- 54,58 ----
LOG4 = _log(4.0)
SG_MAGICCONST = 1.0 + _log(4.5)
+ BPF = 53 # Number of bits in a float
# Translated by Guido van Rossum from C source provided by
***************
*** 132,141 ****
## -------------------- integer methods -------------------
! def randrange(self, start, stop=None, step=1, int=int, default=None):
"""Choose a random item from range(start, stop[, step]).
This fixes the problem with randint() which includes the
endpoint; in Python this is usually not what you want.
! Do not supply the 'int' and 'default' arguments.
"""
--- 133,143 ----
## -------------------- integer methods -------------------
! def randrange(self, start, stop=None, step=1, int=int, default=None,
! maxwidth=1L<<BPF, _BuiltinMethod=_BuiltinMethodType):
"""Choose a random item from range(start, stop[, step]).
This fixes the problem with randint() which includes the
endpoint; in Python this is usually not what you want.
! Do not supply the 'int', 'default', and 'maxwidth' arguments.
"""
***************
*** 147,150 ****
--- 149,154 ----
if stop is default:
if istart > 0:
+ if istart >= maxwidth and type(self.random) is _BuiltinMethod:
+ return self._randbelow(istart)
return int(self.random() * istart)
raise ValueError, "empty range for randrange()"
***************
*** 154,158 ****
if istop != stop:
raise ValueError, "non-integer stop for randrange()"
! if step == 1 and istart < istop:
# Note that
# int(istart + self.random()*(istop - istart))
--- 158,163 ----
if istop != stop:
raise ValueError, "non-integer stop for randrange()"
! width = istop - istart
! if step == 1 and width > 0:
# Note that
# int(istart + self.random()*(istop - istart))
***************
*** 167,171 ****
# a long, but we're supposed to return an int (for backward
# compatibility).
! return int(istart + int(self.random()*(istop - istart)))
if step == 1:
raise ValueError, "empty range for randrange()"
--- 172,178 ----
# a long, but we're supposed to return an int (for backward
# compatibility).
! if width >= maxwidth and type(self.random) is _BuiltinMethod:
! return int(istart + self._randbelow(width))
! return int(istart + int(self.random()*width))
if step == 1:
raise ValueError, "empty range for randrange()"
***************
*** 176,182 ****
raise ValueError, "non-integer step for randrange()"
if istep > 0:
! n = (istop - istart + istep - 1) / istep
elif istep < 0:
! n = (istop - istart + istep + 1) / istep
else:
raise ValueError, "zero step for randrange()"
--- 183,189 ----
raise ValueError, "non-integer step for randrange()"
if istep > 0:
! n = (width + istep - 1) / istep
elif istep < 0:
! n = (width + istep + 1) / istep
else:
raise ValueError, "zero step for randrange()"
***************
*** 184,187 ****
--- 191,197 ----
if n <= 0:
raise ValueError, "empty range for randrange()"
+
+ if n >= maxwidth and type(self.random) is _BuiltinMethod:
+ return istart + self._randbelow(n)
return istart + istep*int(self.random() * n)
***************
*** 191,194 ****
--- 201,227 ----
return self.randrange(a, b+1)
+
+ def _randbelow(self, n, bpf=BPF, maxwidth=1L<<BPF,
+ long=long, _log=_log, int=int):
+ """Return a random int in the range [0,n)
+
+ Handles the case where n has more bits than returned
+ by a single call to the underlying generator.
+ """
+
+ # k is a sometimes over but never under estimate of the bits in n
+ k = int(1.00001 + _log(n-1, 2)) # 2**k > n-1 >= 2**(k-2)
+
+ random = self.random
+ r = n
+ while r >= n:
+ # In Py2.4, this section becomes: r = self.getrandbits(k)
+ r = long(random() * maxwidth)
+ bits = bpf
+ while bits < k:
+ r = (r << bpf) | (long(random() * maxwidth))
+ bits += bpf
+ r >>= (bits - k)
+ return r
## -------------------- sequence methods -------------------
More information about the Python-checkins
mailing list