2012-05-31 5 views
2

(перефразировав вопрос)Эффективное использование распределения форсирования

Я создаю класс обертки для повышения нормального распределения и хочу сделать его максимально эффективным.

Если я использую:

double x = 0.0; 
boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor(rng, nd); 
for (int i=0; i<20; i++) { 
    double x = var_nor(); 
} 

Цикл работает отлично. Меня беспокоит то, что я не хочу объявлять что-либо излишне, поскольку метод вызывается много раз. Я попытался раскалывается код и поместить эту строку в конструкторе:

boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor(rng, nd); 

и есть метод выборки, который делает это:

 double x = var_nor(); 
    return x; 

Но в этом случае, я получаю сообщение об ошибке говорящее var_nor() (т. е. без аргументов) не найден. Может ли кто-нибудь сказать мне, что происходит с этими объявлениями boost? то, что делает

импульс: variate_generate т.д.

линии на самом деле делают в с var_nor? С моим ограниченным знанием C++, похоже, что var_nor определяется двумя разными сигнатурами.

Спасибо, ребята Пит

+4

Конструктор странно: он определил некоторые совершенно бесполезные локальные переменные, и он не может инициализировать какой-либо из членов класса , Может быть, время для хорошей книги на C++? –

ответ

4

В коде var_nor это переменная, а не функция, поэтому она не имеет подписи. Он представляет объект variate_generator, который может вести себя как функция, потому что она поддерживает operator().

В вашем коде вы заявляете и инициализируете var_nor одновременно. Аргументы rng и nd передаются в конструктор объекта variate_generator.

Когда вы переместили заявление в конструкторе вашего класса, вы объявляли var_nor как локальной переменной в конструкторе, так что это не удивительно, что не было доступно в другом месте. Для того, чтобы что-то было доступно во всем классе, оно должно быть переменным-членом . Объявите это частный в классе:

class NormalDistribution 
{ 
    boost::random::mt19937 _rng; 
    boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor; 
public: 
    NormalDistribution(); 
}; 

Затем инициализировать его в конструкторе:

NormalDistribution::NormalDistribution(): 
    _rng(), var_nor(_rng, boost::normal_distribution<>(0.0, 1.0)) 
{ } 

_rng член должен быть объявлен первым, так что он будет инициализирован первым. Параметр nd может быть опущен и заменен на временный объект normal_distribution, переданный непосредственно на конструктор var_nor, как показано выше.

С этими изменениями вы должны иметь возможность использовать один и тот же объект normal_distribution по нескольким вызовам вашей функции sample или любым другим вашим использованием для вашего класса NormalDistribution.

В коде, который вы с тех пор удалили из своего вопроса, вы вводили в заблуждение объявления переменных с объявлениями функций. Вы объявили nd как функцию, получающую два параметра и возвращающую normal_distribution. Аналогично с var_nor. Это была функция, когда вы действительно хотели объект. Вы были смущены, потому что это объект, который действует как функция, но это все еще просто объект.

+0

Thankyou Rob, это очищает его. Я пропустил распознавание перегруженного(). – Pete855217

0

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

// normaldistribution.h 
#ifndef NORMALDISTRIBUTION_H 
#define NORMALDISTRIBUTION_H 

#include <boost/random.hpp> 
#include <boost/random/normal_distribution.hpp> 
class NormalDistribution 
{ 
public: 
    NormalDistribution(); 
    double sample(void); 
private: 
    // Use the boost random number generator 
    boost::mt19937 rng; 
    // Make a variate_generator OBJECT. 
    boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor; 
}; 

#endif // NORMALDISTRIBUTION_H 

// normaldistribution.cpp 
NormalDistribution::NormalDistribution(): 
    rng(), var_nor(rng, boost::normal_distribution<>(0.0, 1.0)) 
{ 
    std::cout << "Called normal distribution constructor, passing up var_nor" << std::endl; 
} 

double NormalDistribution::sample(void) { 
    double x = var_nor(); 
    return x; 
} 

// main.cpp 
#include "normaldistribution.h" 

int main(int argc, char *argv[]) 
{ 
    NormalDistribution *nd = new NormalDistribution(); 
    for (int i=0; i < 10; ++i) 
    { 
     double d = nd->sample(); 
     std::cout << d << std::endl; 
    } 
    return 0; 
} 
+0

Я не вижу оснований для того, чтобы 'rng' и' var_nor' были общедоступными. –

+0

var_nor и rng теперь приватные – Pete855217

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