Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How many random numbers does std::uniform_real_distribution use?

Tags:

c++

random

c++11

I was surprised to see that the output of this program:

#include <iostream>
#include <random>

int main()
{
    std::mt19937 rng1;
    std::mt19937 rng2;
    std::uniform_real_distribution<double> dist;

    double random = dist(rng1);
    rng2.discard(2);

    std::cout << (rng1() - rng2()) << "\n";

    return 0;
}

is 0 - i.e. std::uniform_real_distribution uses two random numbers to produce a random double value in the range [0,1). I thought it would just generate one and rescale that. After thinking about it I guess that this is because std::mt19937 produces 32-bit ints and double is twice this size and thus not "random enough".

Question: How do I find out this number generically, i.e. if the random number generator and the floating point type are arbitrary types?

Edit: I just noticed that I could use std::generate_canonical instead, as I am only interested in random numbers of [0,1). Not sure if this makes a difference.

like image 347
cschwan Avatar asked Jul 22 '13 12:07

cschwan


1 Answers

For template<class RealType, size_t bits, class URNG> std::generate_canonical the standard (section 27.5.7.2) explicitly defines the number of calls to the uniform random number generator (URNG) to be

max(1, b / log_2 R),

where b is the minimum of the number of bits in the mantissa of the RealType and the number of bits given to generate_canonical as template parameter. R is the range of numbers the URNG can return (URNG::max()-URNG::min()+1). However, in your example this will not make any difference, since you need 2 calls to the mt19937 to fill the 53 bits of the mantissa of the double.

For other distributions the standard does not provide a generic way to get any information on how many numbers the URNG has to generate to obtain one number of the distribution.

A reason might be that for some distributions the number uniform random numbers required to generate a single number of the distribution is not fixed and may vary from call to call. An example is the std::poisson_distribution, which is usually implemented as a loop which draws a uniform random number in each iteration until the product of these numbers has reached a certain threshold (see for example the implementation of the GNU C++ library (line 1523-1528)).

like image 66
Andreas Hehn Avatar answered Nov 16 '22 14:11

Andreas Hehn