Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does runif() really have a range: 0<= runif(n) <= 1, as stated in the documentation?

Tags:

random

r

I'm new to R, but the documentation surprised me by stating that runif(n) returns a number in the range 0 to 1 inclusive. I would expect 0 <= runif(n) < 1 -- including 0 and not including 1.

I tested it with n = 100,000,000, and found that it never produced 0 or 1. I realize that the probability of actually hitting specific values in floating point is really small, but still... (There are something like 2^53 values between 0 and 1 in double precision).

So I looked into the source code for R and found in r-source-trunk\src\nmath\runif.c

do 
{
    u = unif_rand();
} while (u <= 0 || u >= 1);
return a + (b - a) * u;

So by design, despite the documentation, it will never ever return a 0 or 1.
Isn't this a bug?

Or at least a problem with the documentation?

like image 276
joeking Avatar asked Jan 24 '18 16:01

joeking


1 Answers

The underlying uniform random number function is defined here and the final outputs use this function:

static double fixup(double x)
{
    /* ensure 0 and 1 are never returned */
    if(x <= 0.0) return 0.5*i2_32m1;
    if((1.0 - x) <= 0.0) return 1.0 - 0.5*i2_32m1;
    return x;
}

Despite this, there are comments of the form /* in [0,1) */ for each of the generator's return functions, which I assume is a mistake given the above.

And of course, the code you noticed in runif.c is preceded by:

/* This is true of all builtin generators, but protect against
       user-supplied ones */

So the min or max will never be returned except in the cases mentioned by @JesseTweedle, which is not the case when just calling runif().

For reference, the magic value i2_32m1 is 1/(2^32-1) so the minimum value you can get from the default generators is 1/(2^33-2) which is approximately 1.16e-10. The maximum value is this amount short of 1.

like image 181
James Avatar answered Oct 16 '22 21:10

James