C ++ 11 Генерация случайных чисел из часто меняющегося диапазона

Q: Как я могу генерировать (много) равномерно распределенные целые числа из априорных неизвестных диапазонов? Каков предпочтительный способ с точки зрения производительности (миллионы сгенерированных чисел)?

Контекст: в моем приложении мне нужно генерировать много псевдослучайных чисел во многих местах. Я использую шаблон синглтона для генератора, чтобы поддерживать воспроизводимость запуска приложения. В моем случае распределение всегда одинаково, но проблема в том, что существует слишком много возможных диапазонов, чтобы предварительно создать объект распределения в стиле C ++ 11.

То, что я попробовал: есть два очевидных решения для этого, во-первых, это иметь одноразовые объекты распределения, а во-вторых, использовать по модулю для преобразования случайного числа из максимально широкого диапазона в желаемое. Но почему-то я сомневаюсь, что это лучше всего 🙂

#include <random>
#include <iostream>
#include "limits.h"using namespace std;

mt19937 mt;
uniform_int_distribution<int> * fixedDist;
uniform_int_distribution<int> * variableDist;

// this version creates and delete dist after just one use
int getIntFromRange1(int from, int to){
variableDist = new uniform_int_distribution<int>(from,to);
int num = (*variableDist)(mt);
delete variableDist;
return num;
}

// this version contains modulo
int getIntFromRange2(int from, int to){
int num = (*fixedDist)(mt);
int diff = to - from;
num = num % diff;
return num + from;
}

int main(){
mt.seed(123456);
fixedDist= new uniform_int_distribution<int>(0,INT_MAX)

int a = getIntFromRange1(1,10); // 1 and 10 are just for illustration
int b = getIntFromRange2(1,10); // can change freely

cout << "a: " << a << endl; // a: 6
cout << "b: " << b << endl; // b: 9

getchar();
}

Повторяющийся вопрос

Различный диапазон

6

Решение

я бы сделал

int getIntFromRange1(int from, int to){
std::uniform_int_distribution<int> dist(from, to);
return dist(mt);
}
10

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

Я бы сделал как в Jarod42 ответ: объекты распределения должны быть легкими, поэтому создание нового распределения, когда вам нужно случайное число, является простым и быстрым (случайный движок стоит дорого).

Однако вы также можете рассмотреть эту реализацию:

inline 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 distribution_type dist;
return dist(mt, param_type(from, to));
}

Смысл в том, что могут быть дистрибутивы, которые должны хранить значения / состояния.

Это, вероятно, не относится к целым числам и равномерному распределению, но интересно, что в N4316 — STD :: RAND замена предлагаемая реализация использует эту технику.

0

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