If I were to produce floating point values in the following way:
template <typename T>
T RandomFromRange(T low, T high){
std::random_device random_device;
std::mt19937 engine{random_device()};
std::uniform_real_distribution<T> dist(low, high);
return dist(engine);
}
template <typename T>
T GetRandom(){
return RandomFromRange
(std::numeric_limits<T>::min(),std::numeric_limits<T>::max());
}
//produce floating point values:
auto num1 = GetRandom<float>();
auto num2 = GetRandom<float>();
auto num3 = GetRandom<float>();
//...
Is it possible that I will ever get back a NaN
, Inf
, or -Inf
?
Let's consider what std::uniform_real_distribution
generates.
Produces random floating-point values i, uniformly distributed on the interval [a, b)
So, that's between std::numeric_limits<foat>::min()
and std::numeric_limits<float>::max()
, including former, but excluding latter. What values do those limits return? They return FLT_MIN
and FLT_MAX
respectively. Well, what are those?
minimum normalized positive floating-point number
maximum representable finite floating-point number
Since neither {positive,negative} infinity, nor NaN is within the range of finite numbers, no they're not generated.
As pointed out by Christopher Oicles, pay attention that FLT_MIN
and by extension, std::numeric_limits<foat>::min()
is the smallest positive representable value.
As pointed out by Chris Dodd, if the range of [min, max)
exceeds std::numeric_limits<float>::max()
, then you would get undefined behaviour and in that case any output, including generating infinity would be possible.
Actually, this causes undefined behavior, because of the requirements for std::uniform_real_distribution
(section 26.5.8.2.2 of the draft spec I have):
explicit uniform_real_distribution(RealType a = 0.0, RealType b = 1.0);
Requires: a ≤ b and b − a ≤ numeric_limits<RealType>::max().
Effects: Constructs a uniform_real_distribution object; a and b correspond to
the respective parameters of the distribution.
Your specific example will overflow that numeric_limits
requirement.
Now you could build a std::uniform_real_distribution<double>
with std::numeric_limits<float>::min
/max
as the bounds, and that should be well-defined. Its also likely that your example will work on most implementations (as they generally promote floats to doubles in internal computations), but it is still hitting undefined behavior.
On implementations where it does't work, I would guess the most likely failure mode would be generating Inf
, as that is what the b-a
would generate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With