С++ повышает нормальные случайные числа в нескольких объектах

Извините, если это глупо. Я новичок в Boost и давно не использовал C++. Это игрушечная проблема, пытающаяся вернуться к ней.

Предположим, у меня есть n игровых автоматов, которые выплачивают R при каждом запуске. R должен нормально распределяться. Среднее значение и дисперсия должны быть разными для каждой машины. Мой текущий код C++11 выглядит так:

нарм.ч:

class narm
{
public:
    narm(int mean, int var); // Constructor takes mean and variance

    double mean;             // Local Mean
    double variance;         // Local Var
    static int counter;      // Static Counter for the number of objects so far
    int num;                 // Which machine am I

    boost::mt19937 random_number_generator;
    boost::normal_distribution<> normal;
    boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor;
};

нарм.cpp

// Static variable
int narm::counter = 0;

// Constructor. Creates the mt19937 generator and normal distribution.
// Then make the generator.
narm::narm(int mean, int var) : random_number_generator(), normal(mean, var), var_nor(random_number_generator, normal)
{
    this->mean = mean;
    this->variance = var;
    num = counter++;

    // Seed the generator. The num is also used, as the constructors
    //    were called so fast that std::time was the same (correct solution?)
    var_nor.engine().seed(std::time(NULL) + getpid() + num );
    // I'm not entirely sure what this does.
    var_nor.distribution().reset();

    // Get random number
    std::cout << num << " : " << var_nor() << std::endl;
}

У меня будет функция play(), которая просто возвращает случайное число.

У меня есть несколько побочных вопросов.

  1. Я немного беспокоюсь о своих семенах. Я убежден, что ни одно из семян не будет таким же, как конструкторы, вызываемые в порядке от 0 до n-1. Таким образом, и std::time, и num всегда увеличиваются. Есть ли что-то еще, о чем мне нужно беспокоиться?
  2. Я не добавил объект mt19937 в инициализатор, потому что у меня еще нет num.

Главный вопрос

Можно ли иметь все эти разные генераторы случайных чисел или мне следует использовать один, который используется всеми объектами? Если лучше использовать один, как мне обрабатывать разные значения среднего/дисперсии для каждого объекта?

Спасибо!


Обновлять

Вот следующие обновления, основанные на ваших комментариях/ответах:

нарм.ч

#include<random>

class narm
{
public:
    narm(int mean, int var);

    int k;
    int num;

    double mean;
    double variance;

    static int counter;
    static std::random_device rd;  // Shared
    static std::mt19937 generator; // Shared

    std::normal_distribution<> distribution;
};

нарм.cpp

#include "narm.h"
#include <random>
#include <iostream>

int narm::counter = 0;

std::random_device narm::rd;
std::mt19937 narm::generator(rd());

narm::narm(int mean, int var) : k(0), num(counter++), distribution(mean, var)
{
    this->mean = mean;
    this->variance = var;

    std::cout << num << " : " << distribution(generator) << std::endl;
}

person kleinric    schedule 13.11.2013    source источник
comment
Вы можете запустить генератор из std::random_device, который будет использовать источник истинной случайности, если это возможно, и давать (надеюсь) хорошие псевдослучайные числа в противном случае.   -  person Mike Seymour    schedule 13.11.2013
comment
Комментарий Майка выше является предпочтительным способом раздачи. К более общей теме инициализаторов: там могут быть произвольные выражения. Например, нет причин, по которым вы не могли бы указать num(counter++), random_number_generator(num) в списке инициализаторов. Вам просто нужно убедиться, что инициализаторы находятся в том же порядке, что и в самом классе, потому что это порядок, в котором C++ будет их вызывать.   -  person Joe Z    schedule 13.11.2013


Ответы (1)


Я немного беспокоюсь о своих семенах.

Поскольку вы говорите, что используете С++ 11, вы можете заполнить генератор из std::random_device, который будет использовать источник истинной случайности, если это возможно, и давать (надеюсь) хорошие псевдослучайные числа в противном случае.

(Кстати, если вы используете C++11, то все это теперь находится в стандартной <random> библиотеке, так что Boost не нужен).

Я не добавил объект mt19937 в инициализатор, потому что у меня еще нет num.

Вы можете изменить порядок элементов, чтобы num инициализировался первым. Конечно, это не имеет значения, если вы используете std::random_device.

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

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

Если лучше использовать один, как мне обрабатывать разные значения среднего/дисперсии для каждого объекта?

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

ВНИМАНИЕ: не используйте это в реальном игровом автомате. Генератор Mersenne Twister не подходит для криптографии, как описано здесь.

person Mike Seymour    schedule 13.11.2013
comment
Я даже не осознавал, что все это на С++ 11! :D Итак, я изначально использовал разные генераторы, потому что не был уверен, сколько общего и будут ли они мешать друг другу из-за разных дистрибутивов. (пс.. спасибо!) - person kleinric; 13.11.2013
comment
Спасибо за предупреждение. Я собираюсь заняться докторской диссертацией по обучению с подкреплением. NARM (N Armed Bandit) — хорошая вводная игрушечная задача в RL, и на данный момент это единственная причина, по которой мне нужна случайность. - person kleinric; 13.11.2013