Si vos poids changent plus lentement qu'ils ne sont dessinés, C ++ 11 discrete_distribution
sera le plus simple:
#include <random>
#include <vector>
std::vector<double> weights{90,56,4};
std::discrete_distribution<int> dist(std::begin(weights), std::end(weights));
std::mt19937 gen;
gen.seed(time(0));//if you want different results from different runs
int N = 100000;
std::vector<int> samples(N);
for(auto & i: samples)
i = dist(gen);
//do something with your samples...
Notez cependant que le c ++ 11 discrete_distribution
calcule toutes les sommes cumulées lors de l'initialisation. Habituellement, vous voulez cela car cela accélère le temps d'échantillonnage pour un coût O (N) unique. Mais pour une distribution en évolution rapide, cela entraînera un coût de calcul (et de mémoire) élevé. Par exemple, si les poids représentaient le nombre d'éléments et que chaque fois que vous en dessinez un, vous le supprimez, vous souhaiterez probablement un algorithme personnalisé.
La réponse de Will https://stackoverflow.com/a/1761646/837451 évite cette surcharge mais sera plus lente à tirer que le C ++ 11 car il ne peut pas utiliser la recherche binaire.
Pour voir qu'il fait cela, vous pouvez voir les lignes pertinentes ( /usr/include/c++/5/bits/random.tcc
sur mon installation Ubuntu 16.04 + GCC 5.3):
template<typename _IntType>
void
discrete_distribution<_IntType>::param_type::
_M_initialize()
{
if (_M_prob.size() < 2)
{
_M_prob.clear();
return;
}
const double __sum = std::accumulate(_M_prob.begin(),
_M_prob.end(), 0.0);
// Now normalize the probabilites.
__detail::__normalize(_M_prob.begin(), _M_prob.end(), _M_prob.begin(),
__sum);
// Accumulate partial sums.
_M_cp.reserve(_M_prob.size());
std::partial_sum(_M_prob.begin(), _M_prob.end(),
std::back_inserter(_M_cp));
// Make sure the last cumulative probability is one.
_M_cp[_M_cp.size() - 1] = 1.0;
}