Search code examples
rrandomprecisionuniform-distribution

runif with .Machine$double.xmax as boundaries


I wanted to generate a random real (I guess rational) number.

To do this I wanted to use runif(1, min = m, max = M) and my thoughts were to set m; M (absolute) as large as possible in order to make the interval as large as possible. Which brings me to my question:

M <- .Machine$double.xmax
m <- -M
runif(1, m, M)
## which returns
[1] Inf

Why is it not returning a number? Is the chosen interval simply too large?

PS

> .Machine$double.xmax
[1] 1.797693e+308

Solution

  • As hinted by mt1022 the reason is in runif C source:

    double runif(double a, double b)
    {
        if (!R_FINITE(a) || !R_FINITE(b) || b < a)  ML_ERR_return_NAN;
    
        if (a == b)
        return a;
        else {
        double u;
        /* This is true of all builtin generators, but protect against
           user-supplied ones */
        do {u = unif_rand();} while (u <= 0 || u >= 1);
        return a + (b - a) * u;
        }
    }
    

    In the return argument you can see the formula a + (b - a) * u which transoform uniformly [0, 1] generated random value in the user supplied interval [a, b]. In your case it will be -M + (M + M) * u. So M + M in case it 1.79E308 + 1.79E308 generates Inf. I.e. finite + Inf * finite = Inf:

    M + (M - m) * runif(1, 0, 1)
    # Inf