У меня большой вектор, я хочу добавить к нему шум с нормальным распределением. то, что я делаю сейчас, тривиально для цикла:
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?
Вот мой взгляд на это:
#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));
}