2015-11-26 2 views
1

Мне дано полагать, что генераторы случайных чисел (RNG) следует выставлять только один раз, чтобы гарантировать, что распределение результатов будет таким, как предполагалось.Использование одного и того же генератора случайных чисел для нескольких функций

Я пишу моделирования методом Монте-Карло в C++, который состоит из главной функции («A») вызов другой функции («В») в несколько раз, когда большое количество случайных чисел генерируется в B.

в настоящее время я делаю следующее B:

void B(){ 
    std::array<int, std::mt19937::state_size> seed_data; 
    std::random_device r; 

    std::generate(seed_data.begin(), seed_data.end(), std::ref(r)); 
    std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); //perform warmup 
    std::mt19937 eng(seq); 

    std::uniform_real_distribution<> randU(0,1); 

    double myRandNum = randU(eng); 

    //do stuff with my random number 
} 

Как вы можете видеть, я создаю новый генератор случайных чисел каждый раз, когда я вызываю функцию В. это, насколько я понимаю, это пустая трата времени - РНГ все еще может генерировать намного больше случайных чисел!

Я экспериментировал с созданием «англ» EXTERN но генерирует ошибку, используя г ++:

об ошибке: «» англ имеет как «Экстерн» и инициализатора Экстерн зЬй :: mt19937 анг (Seq);

Как сделать генератор случайных чисел «глобальным», чтобы я мог его использовать много раз?

+0

Почему бы вам не поместить все объекты RNG, которые вам нужны в структуре, и передать их по ссылке там, где вы хотите? –

ответ

3

Будьте осторожны с правилами одного размера. «Глобалы - зло» - один из них. A RNG должен быть быть глобальным объектом. (Оговорка: каждый поток должен получить свой собственный ГСЧ), я, как правило, завернуть мину в одноплодной карте, а просто высева и нагревая один вверх в начале main() достаточно:

std::mt19937 rng; 

int main() 
{ 
    // (seed global object 'rng' here) 
    rng.dispose(10000); // warm it up 

Для вашего сценария использования (создания нескольких RN за звонок), вам не должно возникнуть проблем с созданием локального дистрибутива для каждого вызова функции.

Еще одна вещь: std::random_device - не ваш друг - он может throw в любое время для всех видов глупых причин. Обязательно заверните его в блок try .. catch. Или, и я рекомендую это, используйте конкретную платформу способ получить истинное случайное число. (В Windows используйте Crypto API. На всем остальном используйте /dev/urandom/.)

Надеюсь, это поможет.

+0

Очень полезно, спасибо. Но как я теперь семя 'rng'?Я попытался (в качестве примера) 'eng (r);' где 'r' является' std :: random_device', но я получаю ошибку "error: no match for call to" (std :: mt19937 {aka std :: mersenne_twister_engine [... вырезано, потому что очень долго ...] /usr/include/c++/4.9/bits/random.h:546:7: примечание: кандидат ожидает 0 аргументов, 1 предоставлен ". Как вы его засеиваете? – NewDogOldTricks

+1

Используйте функцию 'seed()' member: 'rng.seed (your_seed_sequence)'. –

1

Вам не нужно ничего пропускать или ничего не объявлять, так как взаимодействие между mt19937 и uniform_real_distribution осуществляется через глобальные переменные.

std::array<int, std::mt19937::state_size> seed_data; 
std::random_device r; 

std::generate(seed_data.begin(), seed_data.end(), std::ref(r)); 
std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); //perform warmup 
std::mt19937 eng(seq); 


B() 

... 

void B() 
{ 

    std::uniform_real_distribution<> randU(0,1); 
... 
+1

Спасибо за ваш ответ. Но я хочу, чтобы std :: mt19937 был объектом, который я передал по ссылке, и я не смог объявить его вне функции B, потому что кажется, что я не могу инициализировать внешнюю функцию B (std :: mt1997 eng;), а затем позже говорят внутри функции, (eng (seq);). Как мне обойти это? – NewDogOldTricks

+0

'eng (seq)' вызывает конструктор. Вы хотите повторно или применить новое семя? Затем вам нужно сделать 'eng.seed (seq);' –

+1

Я только хочу посеять один раз. Затем вызовите 'randU (eng)' каждый раз после этого, чтобы получить случайное число. – NewDogOldTricks

Смежные вопросы