# Fun with floats

I am on a x86_64 machine, in the ocaml-5.1.0 toplevel:

``````# 1.0 = 1.0 -. min_float;;
- : bool = true
``````

I was surprised by this one.
So, I looked for the smallest float I can get that have the desired behavior:

``````1.0 = 1.0 -. 0.0000000000000001;;
- : bool = false
``````

So now, I can draw a float in [0, 1[ (“0.0 included, 1.0 excluded”) like this:

``````let epsilon =  0.0000000000000001;;
let almost_one = 1.0 -. epsilon;;
let rand = Random.float almost_one;;
``````

I also thought about an (recursive but still) ugly solution:
call Random.float 1.0 until you get something <1.0.

You didn’t ask about it, but in case other readers are wondering about it, this is because the precision of floating-point numbers depends on the exponent of the number being represented (this is what makes it “floating” instead of “fixed”), and for 1.0, the maximum precision is smaller than `min_float`, so that adding or substracting `min_float` does not have any effect. More generally, this phenomenon is quantified by the “unit in the last place” (ULP): Unit in the last place - Wikipedia.

You can also use `Float.pred 1.0`.

Cheers,
NIcolas

8 Likes

I did not know about the existence of Float.pred, thanks!

Note that this solution (rejection sampling) is just fine, given that you will never get `1.0` in practice if you call `Random.float 1.0`. (With the current implementation I believe that the probability for this to happen is 2^{-53}, modulo floating-point approximations).

1 Like