https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82554
Bug ID: 82554 Summary: uniform_real_distribution can generate the upper endpoint Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: b.r.longbons at gmail dot com Target Milestone: --- This is related to #64351 and #63176, for which a totally-bogus fix was applied. There is actually a defect in the standard: it requires `generate_canonical` to return at *least* `bits` (e.g. 53), but correct operation is only possible when it generates *exactly* `bits` since floating-point math rounds rather than truncating like integer math. Furthermore, when `std::uniform_real_distribution`'s parameters have different exponents, the difference must be *subtracted* from the number of bits requested (not possible since `bits` is only a template parameter). I have not considered *all* the details when uniform_real_distribution crosses 0 or its parameters are not exact powers of 2, but the principle of requesting less-than-53 bits certainly still applies. Consider the following horrible, but valid RNG (for easy testing): #include <iomanip> #include <iostream> #include <limits> #include <random> int main() { // seed with -2 instead of -1 because it returns the post-advance state // produces -1, 0, 1, 2, ... std::linear_congruential_engine<uint64_t, 1, 1, 0> engine(-2ULL); std::cout << std::setprecision(std::numeric_limits<double>::max_digits10); std::uniform_real_distribution<double> dist(1.0, 2.0); for (int i = 0; i < 2; ++i) std::cout << dist(engine) << std::endl; // just to prove that yes, they are exact, here are the next values // the different discards are because 1.0 has a different exponent engine.discard(1 << 11); std::cout << dist(engine) << std::endl; engine.discard(1 << 12); std::cout << dist(engine) << std::endl; }