Подтвердить что ты не робот

Должен ли я хранить экземпляр объекта случайного распределения или я могу его воссоздать?

У меня есть этот код:

static std::mt19937 rnd;

// ...

static uint32_t rndInt(uint32_t min, uint32_t max) {
    return std::uniform_int_distribution<uint32_t>(min,max)(rnd);
}

Это хорошая практика или я должен хранить uniform_int_distribution?

4b9b3361

Ответ 1

Я сомневаюсь, что объект распределения дорог для создания и уничтожения, хотя я полагаю, что он может сделать немного больше, чем просто сохранить параметры min,max. Он может предсказывать некоторые полезные значения на основе параметров, например, в очевидной реализации 2**32 % (max-min+1) - это количество различных значений из генератора, которые будут отброшены и повторены.

В принципе, объекту распределения разрешено хранить внутри него некоторые биты энтропии, которые были извлечены из генератора при предыдущем вызове operator(), но не нужны. Эти биты могут использоваться для более позднего вызова operator(). Поэтому, если min==0 и max==1, вы можете получить 32 звонка на operator() в рассылке за звонок на генераторе. Это функция reset(), чтобы очистить это состояние.

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

Ответ 2

Я обычно делаю следующее:

std::uniform_int_distribution<uint32_t> distrib(16, 97);

Затем вы можете называть distrib(rnd) несколько раз, не регенерируя распределение каждый раз.

Способ выполнения операции заставляет репликацию распределять каждый раз, когда вы совершаете вызов. Если ваши параметры min и max исправлены, создайте объект распределения и вызовите его, в противном случае оставайтесь с тем, что у вас есть.

Кстати, я бы сеял rnd, используя time(NULL) или какой-нибудь другой метод семени.

Ответ 3

Энтропия хранится в std::mt19937, что означает, что вы продолжите случайную последовательность, но, как отметил Стив Джессоп, у нее все еще есть некоторые накладные расходы для создания объекта. Если вы ожидаете, что эта функция будет вызываться часто с теми же аргументами, вы можете кэшировать объекты std::uniform_int_distribution<uint32_t> на карте, которая использует std::pair<uint32_t, uint32_t> в качестве ключа.