I am writing a discrete distribution random number generator in a c++ class. The requirements are:
Currently I have two solutions, after initialize random number engine with random_device rd; mt19937 engine;
in class and engine(rd())
in initialize list.
One is to create the discrete_distribution object with discrete_distribution<> *d=new discrete_distribution<>(weight_array,weight_array+weight_array_size)
and store the pointer in the class. Each time I call (*d)(engine) to generate a random number, and I just need to delete the distribution and make a new one to update the weight array.
Another way is to define discrete_distribution<> d
in class and update weight array with d=discrete_distribution<>(weight_array,weight_array+weight_array_size)
, so that we can generate random number with d(engine)
and don't need to worry about pointers.
But it seems that both ways are not classical way to use c++ objects. Are they wrong? Are there any drawbacks to write code this way?
Thanks
Another way is to define
discrete_distribution<> d
in class and update weight array withd=discrete_distribution<>(weight_array,weight_array+weight_array_size)
, so that we can generate random number withd(engine)
and don't need to worry about pointers.
This is perfectly fine, common C++ style to deal with object instances.
In fact many types do not have modifier members because they are assignable.
In this case you could, however use the params()
member to change the weights:
#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();
}
Printing something like
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