2015-06-02 2 views
1

У меня есть класс, который также включает в себя случайное число двигателя и его распределение:Как сделать членную функцию класса в C++ генерировать различное случайное число каждый раз, когда оно вызывается?

#include <iostream> 
#include <cmath> 
#include <random> 
#include <chrono> 

class C 
{ 
    public: 
     typedef std::mt19937_64 engine; 
     typedef std::uniform_real_distribution<double> distribution; 
     . 
     . 
     . 

    protected: 
     engine rng; 
     distribution dist; 
     void func(); 
     . 
     . 
     . 
}; 

Так как конструктор вызывается только один раз, я положил семена в нем:

C::C() 
{ . 
    . 
    . 
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); 
    distribution dist(0.0, pow(10,12)); 
    engine rng(seed); 
} 

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

void C::func() 
{ . 
    . 
    . 
    double randNum = floor(dist(rng)); 
    std::cout << randNum << std::endl;  
    . 
    . 
    . 
} 

Однако каждый время генерирует число 0 как случайное число. Кажется, что dist(rng) не выполняет свою работу.

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

+5

код, который вы показываете для конструктора, кажется, создает * локальные * переменные, которые скрывают члены класса (т.е. вы инициализируете * локальные переменные *, а не * члены *, используемые позже). Не делай этого. – crashmstr

+0

В принципе, удалите «дистрибутив» и «движок» из своего конструктора, сохраняя имена переменных и помещая их в список инициализаторов. – KABoissonneault

+1

@KABoissonneault Нет, это не скомпилируется. Материал должен быть в списке инициализаторов. –

ответ

5

Вы определяете ваши dist и eng переменные в классе

protected: 
    engine rng; 
    distribution dist; // Here 
    void func(); 

И в конструкторе вы определяете другой с таким же именем

C::C() 
{ . 
    . 
    . 
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); 
    distribution dist(0.0, pow(10,12)); // Here 
    engine rng(seed); 
} 

Я предполагаю, что вы хотите, чтобы последние присваивание, а не новая переменная. Затем вы получите номера, которые вы хотите.

C::C() 
{ . 
    . 
    . 
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); 
    dist = distribution(0.0, pow(10,12)); // Here 
    rng = engine(seed); 
} 

Или с инициализацией

C() : dist(0.0, pow(10, 12)), 
    rng(std::chrono::system_clock::now().time_since_epoch().count()) 
+1

Зачем вам копировать их? Почему бы не _initialise_ ?! –

+0

@LightnessRacesinOrbit Если это константы, вы можете, если хотите. Полученный код, скорее всего, будет таким же, и, на мой взгляд, это просто более ясное и более то, как используется OP. Добавлено также –

+0

Я нахожу это менее ясным, самым расточительным и вводящим в заблуждение. Это случай «зачем уходить с дороги, чтобы поступать неправильно». Попасть в привычку «инициализировать, если вы не можете» - это гораздо лучший способ пройти через жизнь. :) –

1

В конструкторе вы создаете локальную переменную dist, скрывающую член класса, в то время как член класса получает по умолчанию инициализируется. По умолчанию инициализируется uniform_real_distribution генерирует значения в диапазоне [0,1), который floor всегда превратится в 0.

+0

Так вот история ... Спасибо! :) – azish

2

Самих близко, но вы действительно должны быть инициализация этих членами:

C::C() 
    : dist(0.0, pow(10, 12)) 
    , rng(std::chrono::system_clock::now().time_since_epoch().count()) 
{} 
Смежные вопросы