boost::random генерировать одно и то же число каждый раз

основной .cpp

#include        "stdafx.h"
#include        "random_generator.h"


        int
main ( int argc, char *argv[] )
{
        cout.setf(ios::fixed);
        base_generator_type base_generator;
        int max = pow(10, 2);
        distribution_type dist(1, max);

        boost::variate_generator<base_generator_type&,
distribution_type > uni(base_generator, dist);
        for ( int i=0; i<10; i++ ) {
                //cout << random_number(2) << endl;
                cout << uni() << endl;
        }

        return EXIT_SUCCESS;

}                               /* ----------  end of function main  ---------- */

random_gemerator.h

#include        "stdafx.h"

#include        <boost/random.hpp>
#include        <boost/generator_iterator.hpp>

typedef boost::mt19937 base_generator_type;
typedef boost::lagged_fibonacci19937 fibo_generator_type;
typedef boost::uniform_int<> distribution_type;
typedef boost::variate_generator<fibo_generator_type&,
distribution_type> gen_type;

        int
random_number ( int bits )
{
        fibo_generator_type fibo_generator;
        int max = pow(10, bits);
        distribution_type dist(1, max);

        gen_type uni(fibo_generator, dist);
        return uni();

}               /* -----  end of function random_number  ----- */

stdafx.h

 #include <iostream>
#include <cstdlib>
#include <cmath>

using namespace std;

каждый раз, когда я запускаю его, все они генерируют одну и ту же числовую последовательность

вроде 77, 33,5, 22,...

как правильно использовать boost:random?


это все. но, возможно, есть небольшая проблема, например:

кажется звук

get_seed(); for (;;) {cout << generate_random() << endl; } // is ok 

он генерирует одно и то же случайное число

int get_random() {get_seed();return generate_random();} for (;;) {cout << get_random() <<endl;}  // output the same random number yet

person mono    schedule 04.12.2009    source источник


Ответы (4)


если вы хотите, чтобы последовательность случайных чисел менялась каждый раз, когда вы запускаете свою программу, вам нужно изменить случайное начальное число, например, инициализировав его текущим временем

вы найдете пример здесь, отрывок:

/*
 * Change seed to something else.
 *
 * Caveat: std::time(0) is not a very good truly-random seed.  When
 * called in rapid succession, it could return the same values, and
 * thus the same random number sequences could ensue.  If not the same
 * values are returned, the values differ only slightly in the
 * lowest bits.  A linear congruential generator with a small factor
 * wrapped in a uniform_smallint (see experiment) will produce the same
 * values for the first few iterations.   This is because uniform_smallint
 * takes only the highest bits of the generator, and the generator itself
 * needs a few iterations to spread the initial entropy from the lowest bits
 * to the whole state.
 */
generator.seed(static_cast<unsigned int>(std::time(0)));
person Gregory Pakosz    schedule 04.12.2009
comment
это все. но, возможно, есть небольшая проблема, например следующая: кажется, звук get_seed(); for (;;) {cout ‹‹ generate_random() ‹‹ endl; } // все в порядке, генерируется одно и то же случайное число int get_random() {get_seed();return generate_random();} for (;;) {cout ‹‹ get_random() ‹‹endl;} // выводится одно и то же случайное число пока что - person mono; 09.12.2009
comment
Я предпочитаю инициализировать PRNG до std::time(NULL) + getpid(). Это гарантирует, что бинарные файлы, запускаемые один за другим в быстрой последовательности, инициализируют свои PRNG по-разному. - person user1202136; 03.04.2012
comment
Для дополнительной безопасности правильным подходом должна быть инициализация PRNG с использованием /dev/random (или эквивалентного в Windows.) - person Avio; 08.06.2016

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

В зависимости от того, что вы делаете с числами, вам может потребоваться подумать о том, как вы выбираете начальное значение. Если вам нужна высококачественная случайность (если вы генерируете криптографические ключи и хотите, чтобы они были достаточно безопасными), вам понадобится хорошее начальное значение. Если бы это был Posix, я бы предложил /dev/random, но вы, похоже, используете Windows, поэтому я не уверен, какой хороший исходный код будет.

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

person R Samuel Klatchko    schedule 04.12.2009
comment
Да правильно. Если начальное число одинаковое, генератор каждый раз будет начинать с одного и того же случайного числа. - person A9S6; 04.12.2009
comment
это все. но, возможно, есть небольшая проблема, например следующая: кажется, звук get_seed(); for (;;) {cout ‹‹ generate_random() ‹‹ endl; } // все в порядке, генерируется одно и то же случайное число int get_random() {get_seed();return generate_random();} for (;;) {cout ‹‹ get_random() ‹‹endl;} // выводится одно и то же случайное число пока что - person mono; 09.12.2009
comment
генерировать семя каждый раз, когда вызывается функция. по сравнению с использованием одного и того же семени каждый раз, которое является одним и тем же семенем? почему я получаю ту же последовательность случайных чисел прежним способом - person mono; 09.12.2009
comment
См. мой комментарий к Крису для абстракции высококачественного случайного источника в Windows. - person Chinasaur; 23.09.2011

Если вы работаете в системе «nix», вы всегда можете попробовать что-то вроде этого;

int getSeed()
{
    ifstream rand("/dev/urandom");
    char tmp[sizeof(int)];
    rand.read(tmp,sizeof(int));
    rand.close();
    int* number = reinterpret_cast<int*>(tmp);
    return (*number);
}

Я предполагаю, что заполнение генератора случайных чисел таким образом быстрее, чем простое чтение /dev/urandom (или /dev/random) для всех ваших потребностей в случайных числах.

person Chris Huang-Leaver    schedule 14.12.2009
comment
Это правильная идея. Обратите внимание, что по крайней мере в более новых версиях Boost все это абстрагируется для вас random_device. В качестве бонуса random_device также должен быть реализован в Windows. К сожалению, если я правильно понимаю, это не реализовано в BSD, потому что BSD /dev/urandom на самом деле не является недетерминированным. Поэтому, если вам нужна совместимость с Linux и Windows, я думаю, вы можете использовать random_device, а если вам нужна совместимость с Linux и BSD, вы можете использовать явное чтение из /dev/urandom. Если вам нужна другая комбинация функциональной совместимости, я думаю, вы сами по себе! - person Chinasaur; 23.09.2011

Вы можете использовать boost::random::random_device либо как есть, либо для заполнения вашего другого генератора.

You can get a one-off random number out of it with a simple:

boost::random::random_device()()

person Alastair Maw    schedule 13.07.2012
comment
Похоже, он возвращает результат типа unsigned int (мне было интересно... так что пришлось поискать). - person Craig McQueen; 16.10.2013