В Stackoverflow есть много вопросов о создании равномерно распределенных целых чисел из неизвестных неизвестных диапазонов. Например.
- С++ 11 Генерация случайных чисел из часто изменяющегося диапазона
- Изменять диапазон равномерного_распределения
Типичное решение - это что-то вроде:
inline std::mt19937 &engine()
{
thread_local std::mt19937 eng;
return eng;
}
int get_int_from_range(int from, int to)
{
std::uniform_int_distribution<int> dist(from, to);
return dist(engine());
}
Учитывая, что распределение должно быть легким объектом, и нет проблем с производительностью, воссоздающих его несколько раз, кажется, что даже простое распространение может очень хорошо и обычно будет некоторое внутреннее состояние.
Итак, мне было интересно, не мешало ли это распределению работать, постоянно перезагружая его (т.е. воссоздавая распределение при каждом вызове get_int_from_range
). Я получаю правильно распределенные результаты.
Там длительное обсуждение между Пит Беккер и Стивом Джессопом, но без окончательного слова. В другом вопросе (Должен ли я хранить экземпляр объекта случайного распределения или я могу его воссоздать?) "проблема" внутреннего состояния не кажется очень важной.
Предоставляет ли стандарт С++ какие-либо гарантии в отношении этой темы?
Является ли следующая реализация (от N4316 - std:: rand replacement) несколько более надежной?
int get_int_from_range(int from, int to)
{
using distribution_type = std::uniform_int_distribution<int>;
using param_type = typename distribution_type::param_type;
thread_local std::uniform_int_distribution<int> dist;
return dist(engine(), param_type(from, to));
}
ИЗМЕНИТЬ
Это повторяет возможное внутреннее состояние распределения, но оно сложное, и я не уверен, что он стоит того, чтобы справиться с проблемой:
int get_int_from_range(int from, int to)
{
using range_t = std::pair<int, int>;
using map_t = std::map<range_t, std::uniform_int_distribution<int>>;
thread_local map_t range_map;
auto i = range_map.find(range_t(from, to));
if (i == std::end(range_map))
i = range_map.emplace(
std::make_pair(from, to),
std::uniform_int_distribution<int>{from, to}).first;
return i->second(engine());
}