I understand that randomIO::IO Float
produces uniformly distributed Float
numbers, but my question is in what range? Is it [0,1]
, (0,1)
or anything in between ([0,1)
or (0,1]
)?
I couldn't find anything about it on hackage, and the referenced paper is behind a paywall.
The reason I'm asking is because you might want to transform the random number, and if you want to evaluate 1/myRandomNumber
it would be helpful to know whether you will ever run into Infinity
or not.
import System.Random
main=(randomIO::IO Float)>>=print
Try it online!
Short answer: the range is [0, 1).
Yes. The implementation of Random
for a Float
is [source]:
instance Random Float where
randomR = randomRFloating
random rng =
-- TODO: Faster to just use 'next' IF it generates enough bits of randomness.
case random rng of
(x,rng') ->
-- We use 24 bits of randomness corresponding to the 24 bit significand:
((fromIntegral (mask24 .&. (x::Int32)) :: Float)
/ fromIntegral twoto24, rng')
-- Note, encodeFloat is another option, but I'm not seeing slightly
-- worse performance with the following [2011.06.25]:
-- (encodeFloat rand (-24), rng')
where
mask24 = twoto24 - 1
twoto24 = (2::Int32) ^ (24::Int32)
It uses a random 32-bit integer x
(where zero is a possible value), it masks out the first 8 bits, and divides that value by 224. As a result the range is 0 (included) to 1 (excluded). The largest value it can represent is 0.999999940395
.
The reason it works that way is because a Float
has a 24-bit mantisse (as well as 7-bit exponent and a sign bit). By transforming it in that range, we guarantee that every Float
value is equally probable: the last 24 bits are first copied into the mantisse of the Float
, then the float is normalized, and the exponent altered such that the values are in the [0, 1) range.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With