Как передать функции распределения в качестве параметров для функции?

#c

Вопрос:

Я хотел бы передать функции случайного распределения (они могут отличаться в зависимости от того, что я хочу, что может измениться), поэтому я хотел бы, чтобы они были функцией параметров по существу, как я могу этого достичь?

 auto GenerateRandomVector(double amp;mean, double amp;SD, int amp;VecSize) -> std::vector<double> {
        std::random_device rnd_device;
        std::mt19937 mersenne_engine {rnd_device()};  
        std::normal_distribution<double> dist {mean, SD}; //Hw do I make this an argument? 

         auto gen = [amp;dist, amp;mersenne_engine]() {
                   return dist(mersenne_engine);
               };

        std::vector<int> vec(VecSize);
        std::generate(vec.begin(), vec.end(), gen);

        return vec;
    }
 

Ответ №1:

Вы просто берете его по ссылке (если хотите сохранить его внутреннее состояние) или передаете по значению.

Пример использования ссылок:

 std::mt19937amp; prng() {
    thread_local std::mt19937 mersenne_engine(std::random_device{}());
    return mersenne_engine;
}

std::vector<double> GenerateRandomVector(doubleamp; mean, doubleamp; SD,
                                         std::size_t VecSize,
                                         std::normal_distribution<double>amp; dist)
{
    auto gen = [amp;dist](){ return dist(prng()); };

    std::vector<double> vec(VecSize);       // Note: `double`, not `int`
    std::generate(vec.begin(), vec.end(), gen);
    mean = std::accumulate(vec.begin(), vec.end(), 0.) / vec.size();

    return vec;
}
 

Примечание: Не инициализируйте новый PRNG каждый раз, когда вы звоните GenerateRandomVector . Инициализируйте один PRNG и используйте его везде, как я показал выше.

Если вам нужно поддерживать другие типы дистрибутивов, вы можете сделать его шаблоном функции:

 template<class Dist>
auto GenerateRandomVector(doubleamp; mean, doubleamp; SD,
                          std::size_t VecSize, Distamp; dist)
{
    using result_type = typename Dist::result_type;

    auto gen = [amp;dist](){ return dist(prng()); };

    std::vector<result_type> vec(VecSize);  //  type depends on Dist
    std::generate(vec.begin(), vec.end(), gen);
    mean = std::accumulate(vec.begin(), vec.end(), 0.) / vec.size();

    return vec;
}
 

Если вы используете C 11, вам необходимо добавить конечный тип возврата:

 template<class Dist>
auto GenerateRandomVector(double amp;mean, double amp;SD, std::size_t VecSize,
                          Distamp; dist) -> std::vector<typename Dist::result_type>
{
 

Комментарии:

1. Что, если вместо этого я захочу использовать дистрибутив? Например, равномерное распределение и все остальные вместо этого? Как бы я смог их передать? Могу ли я просто просто создать шаблон?

2. @Steveit Да, я добавил это в качестве примера

3. это потрясающе, я определенно попробую еще раз!

4. Да, это работает просто отлично, большое вам спасибо!

5. просто вопрос, как мне принять ответ