How many random numbers does std::uniform_real_distribution use?

c++, c++11, random

Solution

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)).

Problem

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.

Original source