Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uniform_real does not accept numeric_limits::lowest()

Tags:

c++

random

c++11

I've got a line:

std::uniform_real_distribution<T> distribution(std::numeric_limits<T>::lowest(), 
                                               std::numeric_limits<T>::max());

It compiles but crashes on Debug(VS 2017CE). My guess is that, according to documentation of std::uniform_real_distribution:

Requires that a ≤ b and b-a ≤ std::numeric_limits<RealType>::max()

when my b is ::max() and a is ::lowest(), condition:

b-a ≤ std::numeric_limits<RealType>::max()

is not fulfilled as b-a basically doubles the value of max. Is there any work around for this so that I will keep such a wide numbers range? ::min() works perfectly but omits negative values. Problem occurs for floating numbers only.

like image 453
PStarczewski Avatar asked Aug 27 '18 12:08

PStarczewski


2 Answers

One simple solution, at least for the common IEEE-754 floating point numbers, would be randomly flipping the sign of a random non-negative number:

std::uniform_real_distribution<T> distribution(0., 
                                               std::numeric_limits<T>::max());
auto rn = distribution(eng);
return someRandomFlag ? rn : -rn;

where someRandomFlag is chosen uniformly from {true, false}.

like image 86
Baum mit Augen Avatar answered Nov 15 '22 22:11

Baum mit Augen


One way to do this is to use the range [-1, 1] and then multiply that by std::numeric_limits<T>::max() to get the actual number. This lets you satisfy the b-a ≤ std::numeric_limits<RealType>::max() requirement.

auto dis = std::uniform_real_distribution<T> dis(-1, std::nextafter(1, std::numeric_limits<T>::max()));
return dis(eng) * std::numeric_limits<T>::max();

This won't give you all possible floating point values but it will give you a good number of them distributed like a uniform_int_distribution would.

like image 25
NathanOliver Avatar answered Nov 15 '22 22:11

NathanOliver