C++11 std::uniform_real_distribution( -1, 1 ) gives numbers in the range [-1,1).
How would you get a uniform real distribution in the range [-1,1]?
Practically it probably doesn't matter but logically I'm trying to select a value in the inclusive range.
This is easier to think about if you start by looking at integers. If you pass [-1, 1) you would expect to get -1, 0
. Since you want to include 1
, you would pass [-1, (1+1)), or [-1, 2). Now you get -1, 0, 1
.
You want to do the same thing, but with doubles:
Borrowing from this answer:
#include <cfloat> // DBL_MAX
#include <cmath> // std::nextafter
#include <random>
#include <iostream>
int main()
{
const double start = -1.0;
const double stop = 1.0;
std::random_device rd;
std::mt19937 gen(rd());
// Note: uniform_real_distribution does [start, stop),
// but we want to do [start, stop].
// Pass the next largest value instead.
std::uniform_real_distribution<> dis(start, std::nextafter(stop, DBL_MAX));
for (auto i = 0; i < 100; ++i)
{
std::cout << dis(gen) << "\n";
}
std::cout << std::endl;
}
(See the code run here)
That is, find the next largest double value after the one you want, and pass that as the end value instead.
Unfortunately the actual implementations of the floating point distributions don't allow you to be so precise. E.g., uniform_real_distribution<float>
is supposed to produce values in a given half range, but due to rounding issues it may in fact produce values in an inclusive range instead.
Here's an example of the problem with generate_cannonical
, and similar problems occur with the other real_distributions.