Générer des nombres aléatoires en utilisant la bibliothèque aléatoire c++11
comme le titre l'indique, j'essaie de trouver un moyen de générer des nombres aléatoires en utilisant la nouvelle bibliothèque C++11 <random>
. J'ai essayé avec ce code:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
le problème avec le code que j'ai est que chaque fois que je le compile et l'exécute, il génère toujours les mêmes nombres. Ma question est donc de savoir quelles autres fonctions de la bibliothèque aléatoire peuvent accomplir ceci tout en étant vraiment aléatoire?
pour mon cas d'utilisation particulière, j'ai été essayer d'obtenir une valeur dans la gamme [1, 10]
4 réponses
Stephan T. Lavavej (stl) de Microsoft a fait un exposé à Going Native sur la façon d'utiliser les nouvelles fonctions aléatoires C++11 et pourquoi ne pas utiliser rand()
. Il y a inclus une diapositive qui résout fondamentalement votre question. J'ai copié le code de la diapositive ci-dessous.
vous pouvez voir son discours complet ici: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
#include <random>
#include <iostream>
int main() {
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<double> dist(1.0, 10.0);
for (int i=0; i<16; ++i)
std::cout << dist(mt) << "\n";
}
nous utilisons random_device
une fois pour lancer le générateur de nombres aléatoires nommé mt
. random_device()
est plus lent que mt19937
, mais il n'a pas besoin d'être semé parce qu'il demande des données aléatoires à partir de votre système d'exploitation (qui va source à partir de divers endroits, comme RdRand par exemple).
en regardant cette question / réponse , il apparaît que uniform_real_distribution
renvoie un nombre dans la gamme [a, b)
, où vous voulez [a, b]
. Pour ce faire, notre uniform_real_distibution
devrait en fait ressembler à:
std::uniform_real_distribution<double> dist(1, std::nextafter(10, DBL_MAX));
Ma bibliothèque 'aléatoire' fournit un wrapper pratique élevé autour de C++11 classes aléatoires. Vous pouvez faire presque toutes les choses avec une méthode simple "get".
exemples:
-
nombre aléatoire dans une fourchette
auto val = Random::get(-10, 10); // Integer auto val = Random::get(10.f, -10.f); // Float point
- "151940920 Aléatoire" boolean
auto val = Random::get<bool>( ) // 50% to generate true auto val = Random::get<bool>( 0.7 ) // 70% to generate true
-
valeur Aléatoire à partir d'un std::initilizer_list
auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or...
-
itérateur aléatoire de la plage des itérateurs ou de tous les contenants
auto it = Random::get( vec.begin(), vec.end() ); // it = random iterator auto it = Random::get( vec ); // return random iterator
et encore plus de choses ! Regardez la page github:
voici quelque chose que je viens d'écrire dans ce sens:
#include <random>
#include <chrono>
#include <thread>
using namespace std;
//==============================================================
// RANDOM BACKOFF TIME
//==============================================================
class backoff_time_t {
public:
random_device rd;
mt19937 mt;
uniform_real_distribution<double> dist;
backoff_time_t() : rd{}, mt{rd()}, dist{0.5, 1.5} {}
double rand() {
return dist(mt);
}
};
thread_local backoff_time_t backoff_time;
int main(int argc, char** argv) {
double x1 = backoff_time.rand();
double x2 = backoff_time.rand();
double x3 = backoff_time.rand();
double x4 = backoff_time.rand();
return 0;
}
~
vous avez deux situations communes. La première est que vous voulez des nombres aléatoires et que vous ne vous souciez pas trop de la qualité ou de la vitesse d'exécution. Dans ce cas, utilisez la macro suivante
#define uniform() (rand()/(RAND_MAX + 1.0))
qui vous donne p dans la gamme de 0 à 1 - epsilon (sauf si RAND_MAX est plus grand que la précision d'un double, mais s'inquiéter de cela quand vous en Venez à elle).
int x = (int) (uniform () * N);
donne maintenant un entier aléatoire sur 0 à N-1.
si vous avez besoin d'autres distributions, vous devez transformer p. Ou parfois il est plus facile d'appeler l'uniforme() plusieurs fois.
si vous voulez un comportement reproductible, semez avec une constante, sinon semez avec un appel au temps().
maintenant si vous vous souciez de la qualité ou de la performance, réécrivez uniform(). Mais sinon, ne touchez pas au code. Toujours garder l'uniforme () sur 0 à 1 moins epsilon. Maintenant vous pouvez envelopper le C++ au hasard Bibliothèque numérique pour créer un meilleur uniforme (), mais c'est une sorte d'option de niveau moyen. Si vous êtes ennuyé par les caractéristiques du RNG, alors il est également intéressant d'investir un peu de temps pour comprendre comment les méthodes sous-jacentes fonctionnent, puis fournir un. Vous avez donc le contrôle total du code, et vous pouvez garantir qu'avec la même graine, la séquence sera toujours exactement la même, quelle que soit la plate-forme ou la version de C++ vers laquelle vous faites le lien.