Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why std::uniform_real_distribution::max() returns the exclusive upper bound?

Tags:

c++

I'm asking mostly out of academic interest.

The documentation says that std::uniform_real_distribution generates numbers in [a,b) range, where a and b are the constructor parameters.

Since the upper bound is exclusive, I expect .max() to return the largest representable value less than .b().

But instead I'm getting .b() == .max() on both GCC, Clang, and MSVC. (For float, double, and long double.) Why?

#include <iostream>
#include <iomanip>
#include <random>

int main()
{
    auto d = std::uniform_real_distribution<long double>(0, 1);
    std::cout << std::setprecision(1000);
    std::cout << d.min() << '\n'; // 0
    std::cout << d.a() << '\n';   // 0 
    std::cout << d.max() << '\n'; // 1 <- Here I expect 0.99999...
    std::cout << d.b() << '\n';   // 1
}

I found this note saying that some common implementation use [a,b] range for float only. It could explain .b() == .max() for float, but not for double and long double.


I think it might be educational to also print std::nextafter(d.b(), d.a()). – StoryTeller

For long double it evaluates to 0.9999999999999999999457898913757247782996273599565029144287109375, which is what I'd expect to get from .max().

like image 490
HolyBlackCat Avatar asked Sep 16 '18 14:09

HolyBlackCat


People also ask

What is uniform_real_distribution class in random library in C++?

C++ have introduced uniform_real_distribution class in the random library whose member function give random real numbers or continuous values from a given input range with uniform probability. Public member functions in uniform_real_distribution class: operator (): This function returns a random value from the range given.

What is uniform distribution in C++ with example?

std::uniform_real_ distribution class in C++ with Examples. In Probability, Uniform Distribution Function refers to the distribution in which the probabilities are defined on a continuous random variable, one which can take any value between two numbers, then the distribution is said to be a continuous probability distribution.

Why does uniform_real_distribution() produce values in an inclusive range?

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.

Does uniform_real_distribution satisfy all requirements of randomnumberdistribution?

. std::uniform_real_distribution satisfies all requirements of RandomNumberDistribution The result type generated by the generator. The effect is undefined if this is not one of float, double, or long double . the type of the parameter set, see RandomNumberDistribution .


1 Answers

I do not think the bug is about floats specifically, but for floating point numbers in general.

The bug was already mentioned in VS-Dev-Community where this problem is addressed with regards to doubles. However, they claim to have it fixed as of Jan 26, 2021.

On a side note: Also, I cannot reproduce the max() value you get for long double. I get 1 as in all other cases. As mentioned before, it is just random noise, since setprecision(n) seems to produce noise for n > numeric_limits::max_digits10.

like image 131
CasualCay Avatar answered Sep 18 '22 05:09

CasualCay