Générateur de nombres aléatoires biaisés

Je cherche un générateur de nombres aléatoires qui puisse être biaisé. Par exemple, disons que je veux un nombre aléatoire compris entre 1 et 5, avec la probabilité d’être:

1: arrive 20% du temps
2: arrive 10% du temps
3: arrive 40% du temps
4: arrive 25% du temps
5: arrive 5% du temps

Y a-t-il quelque chose dans la bibliothèque standard ou dans d’autres bibliothèques qui ferait cela? Sinon, existe-t-il un moyen efficace de le faire moi-même?

La bibliothèque de nombres aléatoires Boost permet de spécifier différentes dissortingbutions de formes pour votre générateur. C’est une excellente bibliothèque – voir http://www.boost.org/doc/libs/1_42_0/libs/random/index.html .

Pour votre problème, il suffit de choisir un élément aléatoire de cette liste de manière uniforme:

[1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5] 

En général, cochez cette réponse: Nombres aléatoires pondérés


Dans TR1 et C ++ 0x, il existe tête qui contient la classe discrete_dissortingbution pour générer de tels nombres, entre autres.

Vous pouvez également consulter GSL, qui contient beaucoup plus de dissortingbutions aléatoires (et de générateurs de nombres aléatoires) que la bibliothèque standard . (Notez cependant que GSL utilise la GPLv3.)

Le meilleur moyen est probablement de prendre le générateur aléatoire non biaisé normal puis de revenir en fonction de l’intervalle dans lequel sa valeur se situe.

Juste une instruction if qui donne 1 pour 0: 0,2, 2 pour 0,2: 0,3, 3 pour 0,3: 0,7, 4 pour 0,7: 0,95 et 5 pour 0,95: 1. Il est préférable de définir la limite inférieure ou supérieure de l’intervalle et l’autre exclusive.

 int biasedRandom(){ double i = randomNumber(); if(i<= 0.2){return 1;} else if(i <= 0.3){return 2;} else if(i <= 0.7){return 3;} else if(i <= 0.95){return 4;} else{return 5;} } 

Quelque chose comme ca.

Ce que vous décrivez est l’implémentation d’un générateur de nombres aléatoires qui s’inspire d’une dissortingbution de probabilité particulière. Par exemple, dessiner des nombres dans une dissortingbution gaussienne devrait dessiner des nombres aléatoires tels que la probabilité d’un tirage particulier, x soit proportionnelle au texte alt http://upload.wikimedia.org/math/1/8/4/184fa5540b76903b1653d9f83912265d.png .

En général, l’approche consiste à s’appuyer sur une dissortingbution aléatoire uniforme, puis à choisir la valeur de la fonction de dissortingbution cumulative (CDF) de la dissortingbution souhaitée à l’emplacement dessiné. Dans le cas d’une gaussienne normale, tracez un nombre aléatoire, x à partir d’une dissortingbution uniforme (c’est ce que les générateurs de nombres aléatoires standard doivent donner), puis choisissez texte alternatif comme la valeur aléatoire, dissortingbuée gaussienne. Pour votre cas, le CDF que vous décrivez est une fonction d’escalier continu par morceaux qui pourrait être mise en œuvre en utilisant l’une des nombreuses réponses (correctes) que vous avez déjà reçues.

Bien sûr, tout cela est sortingvial. Ce que vous devriez faire, c’est utiliser une bibliothèque qui gère déjà cela pour vous. Les statistiques et la génération de nombres aléatoires ne sont pas anodines et il n’est pas nécessaire de réinventer la roue. Voir la réponse de Neil (et consultez la bibliothèque de nombres aléatoires Boost).

Venir tard à la fête sur celui-ci. Voici la réponse C ++ 0x:

 #include  #include  #include  int main() { // Set up dissortingbution double interval[] = {1, 2, 3, 4, 5, 6}; double weights[] = { .2, .1, .4, .25, .05}; std::piecewise_constant_dissortingbution<> dist(std::begin(interval), std::end(interval), std::begin(weights)); // Choose generator std::mt19937 gen; // seed as wanted // Demonstrate by pouring into avg[rand-1] const unsigned N = 1000000; double avg[sizeof(weights) / sizeof(weights[0])] = {0}; for (unsigned i = 0; i < N; ++i) avg[static_cast(dist(gen)) - 1]++; // Comute averages for (double* i = std::begin(avg); i < std::end(avg); ++i) *i /= N; // Display for (unsigned i = 1; i <= sizeof(avg)/sizeof(avg[0]); ++i) std::cout << "avg[" << i << "] = " << avg[i-1] << '\n'; } 

Lesquels pour moi sorties:

 avg[1] = 0.199779 avg[2] = 0.100002 avg[3] = 0.400111 avg[4] = 0.250257 avg[5] = 0.049851 

Pourquoi n’utilisez-vous pas simplement un générateur de nombres aléatoires réguliers renvoyant un nombre compris entre 0,0 et 1,0 et l’enveloppez-vous d’une autre fonction qui renvoie un nombre en fonction de vos besoins?

comme

 double biased (double seed) { if (seed >= 0.0 && seed <0.2) return 1; else if ... } 

Lance un nombre réel aléatoire x dans [0,1], if 0< x<0.2 return 1 , if 0.2 , etc.

Voir ici pour le problème général.

Kenny a donné une réponse adaptée à votre dissortingbution de fréquence.

La réponse plus générale fonctionne avec une fonction de dissortingbution CDF – Cumulative Dissortingbution – pour les données et utilise un nombre aléatoire uniforme pour sélectionner une valeur dans la dissortingbution.

Je fais la même chose et j’ai trouvé ceci: http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/

Semble assez bien pour le but que vous avez déclaré.

 #include  #include  #include  #include  int main() { unsigned int seed = 42; boost::mt19937 generator(seed); // return 0 with probability 10% // 1 40% // 2 50% boost::random::discrete_dissortingbution custom_dist{1,4,5}; boost::variate_generator > rndn(generator, custom_dist); for (unsigned int i = 0; i<10000; i++) { std::cout << rndn() << std::endl; } return 0; } 

Et voici un graphique du résultat:

Sortie