как попросить boost :: normal_distribution для генерации большого вектора случайных величин без цикла for

У меня большой вектор, я хочу добавить к нему шум с нормальным распределением. то, что я делаю сейчас, тривиально для цикла:

for (int i=0 ; i<size ; i++){    //size is of order 1000000
boost::mt19937 gen;
gen.seed(i);
boost::normal_distribution<>  nd(0.0 , 1.0);
boost::variate_generator<boost::mt19937&, boost::normal_distribution<> >
randNormal (gen,nd);

noise = randNormal();
nsyData[i] = data[i] + sd*noise;
}

Есть ли эффективный способ сделать это? как то, что делает MATLAB?

1

Решение

Вот мой взгляд на это:

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

int main()
{
boost::mt19937 gen(42); // seed it once
boost::normal_distribution<double> nd(0.0, 1.0);
boost::variate_generator<boost::mt19937&, boost::normal_distribution<double> > randNormal(gen, nd);

std::vector<double> data(100000, 0.0), nsyData;
nsyData.reserve(data.size());

double sd = 415*randNormal();
std::transform(data.begin(), data.end(), std::back_inserter(nsyData),
[sd,&randNormal](double data) { return data + sd*randNormal(); });

}

Обратите внимание, что вы посеивали мерсенновый твистер на каждой итерации цикла. Я боюсь, что это полностью убило любые гарантии качества генерируемых случайных чисел. Семя ваш генератор один раз. (Используйте другое начальное число, например, из random_device, если вам нужно, чтобы оно было недетерминированным, очевидно).

Видеть это Жить на Колиру

Обновить После некоторых комментариев в комментариях, вот версия на С ++ 03, которая на самом деле не должна быть слишком плохой, но все же понятной:

#include <boost/random/normal_distribution.hpp>
#include <boost/random.hpp>
#include <boost/bind.hpp>

struct Xfrm {
typedef double result_type;

template <typename Gen>
double operator()(double sd, Gen& randNormal, double data) const {
return data + sd*randNormal();
}
};

int main()
{
boost::mt19937 gen(42); // seed it once
boost::normal_distribution<double> nd(0.0, 1.0);
boost::variate_generator<boost::mt19937&, boost::normal_distribution<double> > randNormal(gen, nd);

std::vector<double> data(100000, 0.0), nsyData;
nsyData.reserve(data.size());

double sd = 415*randNormal();

std::transform(data.begin(), data.end(), std::back_inserter(nsyData),
boost::bind(Xfrm(), sd, boost::ref(randNormal), ::_1));
}
4

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


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