mt19937 иiform_real_distribution

Я пытаюсь найти эффективный способ реализации равномерного (0,1) распределения. Поскольку мне нужно создать очень большое количество образцов, я выбрал mt19937 в качестве двигателя. Я использую версию из библиотеки Boost. Мой вопрос: в чем разница между использованием выходных данных самого движка по сравнению с использованиемiform_real_distribution?

Опция 1

std::random_device rd;
boost::mt19937 gen(rd());
boost::random::uniform_real_distribution<double> urand(0, 1);

for ( int i = 0; i < 1E8; i++ ) {
u = urand(gen);
}

Вариант № 2

std::random_device rd;
boost::mt19937 gen(rd());

for ( int i = 0; i < 1E8; i++ ) {
u = (double) gen()/gen.max();
}

Согласно моим тестам, вариант № 2 значительно лучше, чем вариант № 1 с точки зрения времени выполнения. Есть ли причина, по которой я должен выбрать вариант № 1 вместо варианта № 2?

5

Решение

Я не знаю основную реализацию urand(), но использование результата деления может привести к смещению в младших разрядах в качестве эффекта квантования. Если gen.max() не велик, то «младшие биты» могут быть очень многими или большей частью битов результата.

Несоответствие производительности может быть вызвано производством правильно распределенных случайных чисел. Если double является слишком точным для ваших нужд, то, возможно, используя float может позволить ему работать более эффективно.

1

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

Мой вопрос: в чем разница между использованием выходных данных самого движка по сравнению с использованиемiform_real_distribution?

В вашем первом варианте urand() имеет диапазон [0,1)тогда как ваш второй вариант имеет диапазон [0,1] (если boost::mt19937::min() == 0, который обычно имеет место).

0

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