2016-11-22 3 views
1

C++ STL 11 Решение:Использование станд :: преобразования с станд :: normal_distribution и станд :: затруднительное

auto distribution = std::bind(std::normal_distribution<double>{mean, stddev}, 
           std::mt19937(std::random_device{}()) 
          ); 
std::transform(data.begin(), data.end(), data.begin(), 
       std::bind(std::plus<double>(), std::placeholders::_1, distribution())); 

Easy диапазон на основе цикла:

for (auto& d : data) { 
    d += distribution(); 
} 

Мой СТЛ решение Безразлично» t, поскольку он всегда принимает первое число, которое оно генерирует из распределения. Я попытался с помощью заполнителя в качестве третьего параметра, но ничего не изменил. Все мои данные увеличиваются на тот же номер, который я не хочу. Я хочу, чтобы такое же поведение, как цикл на основе диапазона.

Это что-то возможно?

+0

возможно использовать lambdas вместо – jaggedSpire

+2

'distribution()' будет вызываться только один раз в вашем первом фрагменте кода, и результат будет привязан к 'plus'. Однако вы хотите, чтобы 'distribution' вызывал для каждого элемента. Вы должны использовать другую семантику. Обратите внимание, что лямбда сделает это легче, например. '[& distribution] (double x) {return x + = distribution(); } '. – Zeta

+0

@ Зета, вот что я подумал. использование лямбда кажется единственным путем? –

ответ

1

Давайте перепишем ваш второй bind, как лямбда, чтобы получить ощущение, как это на самом деле работает:

auto func = std::bind(std::plus<double>(), std::placeholders::_1, distribution()) 

эквивалентно слишком

auto d = distribution(); 

auto func = [d](double x){ return std::plus<double>()(x,d); }; 

или, если мы используем 14 C++ в функции инициализации:

auto func = [d=distribution()](double x){ return std::plus<double>()(x,d); }; 

Как вы можете видеть, distribution() вызывается только один раз. Однако вы не хотите использовать возвращаемое значение distribution, вы хотите позвонить distribution за каждый звонок func. Хотя это можно сделать с помощью bind, лямбда будет сделать это намного проще:

std::transform(data.begin(), data.end(), data.begin(), 
       [&distribution](double x){ return x + distribution(); }); 

А по-моему, это намного проще, чем читать предыдущей bind. Обратите внимание, что std::bind (или, скорее, boost::bind) предшествует лямбда. В C++ 11 было some issues with lambdas по сравнению с std::bind, но с C++ 14 лямбды, как правило, намного легче обрабатывать, читать и понимать, не жертвуя большим количеством.

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