Будет «от мин до макс» Равномерное реальное распределение производят Inf, -Inf или NaN?

Если бы я производил значения с плавающей точкой следующим образом:

template <typename T>
T RandomFromRange(T low, T high){
std::random_device random_device;
std::mt19937 engine{random_device()};
std::uniform_real_distribution<T> dist(low, high);
return dist(engine);
}

template <typename T>
T GetRandom(){
return RandomFromRange
(std::numeric_limits<T>::min(),std::numeric_limits<T>::max());
}

//produce floating point values:
auto num1 = GetRandom<float>();
auto num2 = GetRandom<float>();
auto num3 = GetRandom<float>();
//...

Возможно ли, что я когда-нибудь вернусь NaN, Inf, или же -Inf?

6

Решение

Давайте посмотрим, что std::uniform_real_distribution генерирует.

Создает случайные значения с плавающей точкой i, равномерно распределенные по интервалу [a, b)

Итак, это между std::numeric_limits<foat>::min() а также std::numeric_limits<float>::max(), включая первое, но исключая второе. Какие значения возвращают эти ограничения? Они вернулись FLT_MIN а также FLT_MAX соответственно. Ну что это?

нормализованный минимум положительный число с плавающей точкой

максимальное представимое конечное число с плавающей точкой

Поскольку ни {положительная, отрицательная} бесконечность, ни NaN не находятся в диапазоне конечных чисел, они не генерируются.

Как отметил Кристофер Оиклз, обратите внимание, что FLT_MIN и, соответственно, std::numeric_limits<foat>::min() самый маленький положительный представительная ценность.

Как указал Крис Додд, если диапазон [min, max) превышает std::numeric_limits<float>::max(), тогда вы получите неопределенное поведение, и в этом случае будет возможен любой вывод, включая генерацию бесконечности.

9

Другие решения

На самом деле, это вызывает неопределенное поведение, из-за требований к std::uniform_real_distribution (раздел 26.5.8.2.2 проекта спецификации у меня есть):

explicit uniform_real_distribution(RealType a = 0.0, RealType b = 1.0);
Requires: a ≤ b and b − a ≤ numeric_limits<RealType>::max().
Effects: Constructs a uniform_real_distribution object; a and b correspond to
the respective parameters of the distribution.

Ваш конкретный пример будет переполнен, что numeric_limits требование.

Теперь ваша очередь мог построить std::uniform_real_distribution<double> с std::numeric_limits<float>::min/max как границы, и это должно быть четко определено. Также вероятно, что ваш пример будет работать на большинстве реализаций (так как они обычно продвигают числа с плавающей запятой во внутренних вычислениях), но он все еще поражает неопределенное поведение.

На реализациях, где это не работает, я бы предположил, что наиболее вероятный режим отказа будет генерировать Inf, как это то, что b-a будет генерировать.

6

По вопросам рекламы [email protected]