Как повторно использовать и повторно инициализировать C++ discrete_distribution в классе?

Я пишу дискретный генератор случайных чисел в классе C++. Требования следующие:

  1. Я не хочу создавать объект discrete_distribution каждый раз, когда я его использую. Я знаю, что объект распределения легкий, но мой массив весов настолько длинный, что стоимость все еще слишком высока. Кроме того, мне нужно использовать объект распределения в различных функциях этого класса.
  2. Мне нужно время от времени менять распределение (весовой массив)
  3. Я не знаю точное распределение (весовой массив), когда класс построен

В настоящее время у меня есть два решения, после инициализации двигателя случайных чисел с random_device rd; mt19937 engine; в классе и engine(rd()) в списке инициализации.

Одним из них является создание объекта discrete_distribution с discrete_distribution<> *d=new discrete_distribution<>(weight_array,weight_array+weight_array_size) и сохранить указатель в классе. Каждый раз, когда я вызываю (*d)(engine), чтобы сгенерировать случайное число, мне просто нужно удалить распределение и создать новое для обновления массива весов.

Другой способ - определить discrete_distribution<> d в классе и обновите массив веса с d=discrete_distribution<>(weight_array,weight_array+weight_array_size), так что мы можем сгенерировать случайное число с d(engine) и не нужно беспокоиться о указателях.

Но кажется, что оба способа не являются классическим способом использования объектов C++. Они не правы? Есть ли недостатки для написания кода таким образом?

Спасибо

1 ответ

Решение

Другой способ - определить discrete_distribution<> d в классе и обновите массив веса с d=discrete_distribution<>(weight_array,weight_array+weight_array_size), так что мы можем сгенерировать случайное число с d(engine) и не нужно беспокоиться о указателях.

Это прекрасно, общий стиль C++ для работы с экземплярами объектов.

На самом деле многие типы не имеют членов-модификаторов, потому что они назначаются.

В этом случае вы можете, однако, использовать params() Член для изменения веса:

Жить на Колиру

#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <iostream>

namespace br = boost::random;

struct X {
    using Weight = double;
    br::mt19937                            engine { br::random_device{}() };
    br::discrete_distribution<int, Weight> dist   { {0.2, 0.2, 0.2, 0.2, 0.2} };

    void sample() {
        for (auto i : {1,2,3,4})
            std::cout << "#" << i << ":" << dist(engine) << " ";
        std::cout << "\n";
    }

    void show_probabilities() {
        boost::copy(dist.param().probabilities(), std::ostream_iterator<Weight>(std::cout << "probabilities: ", " "));
        std::cout << "\n";
    }

    void reprogram(std::initializer_list<Weight> probabilities) {
        dist.param(probabilities);
    }
};

int main() {
    X x;
    x.show_probabilities();
    x.sample();

    x.reprogram({0.01, 0.99});

    x.show_probabilities();
    x.sample();
}

Печать что-то вроде

probabilities: 0.2 0.2 0.2 0.2 0.2 
#1:1 #2:2 #3:0 #4:4 
probabilities: 0.01 0.99 
#1:1 #2:1 #3:1 #4:1 
Другие вопросы по тегам