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]?
Practical
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.
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.