I\'m trying to generate in python random floats in the range of [0.8,0.9] , but unfortanetly all the tools i found could only generate randoms in the range of [a,b) for floa
The probability of generating exactly an endpoint value should be negligible. What bad consequences do you worry about if you just use Random.uniform(0.8,0.9)
? (And are you also worried about the fact that the double-precision floats you get when you say "0.8
" and "0.9
" aren't in fact exactly 8/10 and 9/10?)
It's possible that you have very unusual requirements; but for, say, 99.9% of applications I think the answer is: just use Random.uniform(a,b)
and don't worry about it.
The docs say that uniform(a, b)
generates a number in [a, b]1, but this appears to be a documentation error, since the source shows it to rely on random()
, which, according to the docs, returns [0.0, 1.0)2.
If you must have [a, b], then you can try generating this range from an integer:
random.inclusive_uniform = lambda a, b:
random.randint(0, 0xFFFFFFFF) / float(0xFFFFFFFF) * (b - a) + a
I say "try" generating this range, because when the bounds cannot be precisely represented (neither 0.8 and 0.9 can be precisely represented in IEEE-754), then the range is actually [a', b'], where a' and b' are whatever a and b get rounded to. Note that this might even be greater than the range [a, b], so beware!
1 Specifically, it says that return value N
is limited to a <= N <= b
.
2 In a comment in the source, however, is an assertion that it can never actually be 0.0, so I guess range is actually (0.0, 1.0).
The difference between [0.8, 0.9] and [0.8,0.9) is vanishingly small. Given the limitations of binary floating-point, I don't think there even is a difference, since 0.9 can't be precisely represented anyway. Use [0.8,0.9).
If it really matters, then you can do this:
def uniform_closed(a, b):
while True:
r = random.uniform(a, b + (b - a) * 0.01)
if r <= b: return r
Quoting the random.uniform()
docstring:
Get a random number in the range [a, b) or [a, b] depending on rounding.
So you don't even know if the endpoint is included or not. But you should not care either -- there are 900719925474100 floating point numbers in the range [0.8, 0.9]. It will take a lifetime until a single one of them occurs anyway, so there is no practical difference to including the endpoint or not, even if the endpoint can be represented exactly as a floating point number.