Take advantage of the math library's ldexp for assembling a float by

components without division and without roundoff error for properly
sized mantissas (i.e. on systems with 53 or more mantissa bits per
float).  Eliminates the previous implementation's rounding bias as
aptly demonstrated by Tim Peters.
This commit is contained in:
Raymond Hettinger 2004-08-31 01:05:15 +00:00
parent daec961e09
commit 3fa19d7ff8

View file

@ -43,7 +43,7 @@ from warnings import warn as _warn
from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType
from math import log as _log, exp as _exp, pi as _pi, e as _e 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 from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
from math import floor as _floor from math import floor as _floor, ldexp as _ldexp
__all__ = ["Random","seed","random","uniform","randint","choice","sample", __all__ = ["Random","seed","random","uniform","randint","choice","sample",
"randrange","shuffle","normalvariate","lognormvariate", "randrange","shuffle","normalvariate","lognormvariate",
@ -63,13 +63,11 @@ try:
from binascii import hexlify as _hexlify from binascii import hexlify as _hexlify
except ImportError: except ImportError:
_urandom = None _urandom = None
else:
_tofloat = 2.0 ** (-7*8) # converts 7 byte integers to floats
# Translated by Guido van Rossum from C source provided by # Translated by Guido van Rossum from C source provided by
# Adrian Baddeley. Adapted by Raymond Hettinger for use with # Adrian Baddeley. Adapted by Raymond Hettinger for use with
# the Mersenne Twister core generator. # the Mersenne Twister and os.urandom() core generators.
import _random import _random
@ -761,7 +759,7 @@ class HardwareRandom(Random):
"""Get the next random number in the range [0.0, 1.0).""" """Get the next random number in the range [0.0, 1.0)."""
if _urandom is None: if _urandom is None:
raise NotImplementedError('Cannot find hardware entropy source') raise NotImplementedError('Cannot find hardware entropy source')
return long(_hexlify(_urandom(7)), 16) * _tofloat return _ldexp(long(_hexlify(_urandom(7)), 16) >> 3, -BPF)
def getrandbits(self, k): def getrandbits(self, k):
"""getrandbits(k) -> x. Generates a long int with k random bits.""" """getrandbits(k) -> x. Generates a long int with k random bits."""