arman arman - 9 days ago 8
C++ Question

What is the range limit for uniform real distributions?

I want to create a random number within the numeric limits of the

double
floating point range. I thought this would be easy:

#include <random>
#include <cassert>
#include <math.h>

int main()
{
double a = std::numeric_limits<double>::lowest();
double b = std::numeric_limits<double>::max();

std::default_random_engine engine;

std::uniform_real_distribution<double> dist(a, b);
assert(std::isfinite(dist(engine))); // this triggers!

return 0;
}


The assert fails for both
clang 3.8.0
and
gcc 5.4.0
, because apparently the result of
dist(engine)
is
inf
. I tried using
nextafter(a,0)
and
nextafter(b,0)
instead of
a
and
b
when constructing
dist
but got the same result.

According to
std::uniform_real_distribution
, the methods
min
and
max
should provide the range of numbers that will be returned, but apparently that's not the case:

std::cout << dist.min() << ", " << dist.max() << std::endl;


The output of this is:


-1.79769e+308, 1.79769e+308


And, as expected, the following assert triggers, demonstrating the contradiction:

const auto rand = dist(engine);
assert(rand <= dist.max() && rand >= dist.min());


Again, same result for both compilers. As per the definitions of
min
and
max
, the above assert shouldn't be triggering. What's going on?

Answer

Your code exhibits undefined behaviour, as it breaks the following condition:

N4140 § 26.5.8.2.2 [rand.dist.uni.real]

explicit uniform_real_distribution(RealType a = 0.0, RealType b = 1.0);

Requires: a ≤ b and b − a ≤ numeric_limits<RealType>::max().