C ++ 11 vous offre de nombreuses nouvelles options avec random
. L'article canonique sur ce sujet serait N3551, Génération de nombres aléatoires en C ++ 11
Pour voir pourquoi l'utilisation rand()
peut être problématique, voir le matériel de présentation rand () Considered Harmful de Stephan T. Lavavej donné lors de l' événement GoingNative 2013 . Les diapositives sont dans les commentaires mais voici un lien direct .
Je couvre également boost
ainsi que l'utilisation rand
car le code hérité peut encore nécessiter son support.
L'exemple ci-dessous est distillé à partir du site cppreference et utilise le moteur std :: mersenne_twister_engine et le std :: uniform_real_distribution qui génère des nombres dans l' [0,10)
intervalle, avec d'autres moteurs et distributions commentés ( voir en direct ):
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
int main()
{
std::random_device rd;
//
// Engines
//
std::mt19937 e2(rd());
//std::knuth_b e2(rd());
//std::default_random_engine e2(rd()) ;
//
// Distribtuions
//
std::uniform_real_distribution<> dist(0, 10);
//std::normal_distribution<> dist(2, 2);
//std::student_t_distribution<> dist(5);
//std::poisson_distribution<> dist(2);
//std::extreme_value_distribution<> dist(0,2);
std::map<int, int> hist;
for (int n = 0; n < 10000; ++n) {
++hist[std::floor(dist(e2))];
}
for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
la sortie sera similaire à la suivante:
0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****
La sortie variera en fonction de la distribution que vous choisissez, donc si nous décidions d'aller avec std :: normal_distribution avec une valeur 2
à la fois pour la moyenne et stddev, par exemple, dist(2, 2)
la sortie serait similaire à ceci ( voir en direct ):
-6
-5
-4
-3
-2 **
-1 ****
0 *******
1 *********
2 *********
3 *******
4 ****
5 **
6
7
8
9
Ce qui suit est une version modifiée d'une partie du code présenté dans N3551
( voir en direct ):
#include <algorithm>
#include <array>
#include <iostream>
#include <random>
std::default_random_engine & global_urng( )
{
static std::default_random_engine u{};
return u ;
}
void randomize( )
{
static std::random_device rd{};
global_urng().seed( rd() );
}
int main( )
{
// Manufacture a deck of cards:
using card = int;
std::array<card,52> deck{};
std::iota(deck.begin(), deck.end(), 0);
randomize( ) ;
std::shuffle(deck.begin(), deck.end(), global_urng());
// Display each card in the shuffled deck:
auto suit = []( card c ) { return "SHDC"[c / 13]; };
auto rank = []( card c ) { return "AKQJT98765432"[c % 13]; };
for( card c : deck )
std::cout << ' ' << rank(c) << suit(c);
std::cout << std::endl;
}
Les résultats ressembleront à:
5H 5S COMME 9S 4D 6H TH 6D KH 2S QS 9H 8H 3D KC TD 7H 2D KS 3C TC 7D 4C QH QC QD JD AH JC AC KD 9D 5C 2H 4H 9C 8C JH 5D 4S 7C AD 3S 8S TS 2C 8D 3H 6C JS 7S 6S
Renforcer
Bien sûr, Boost.Random est toujours une option également, ici j'utilise boost :: random :: uniform_real_distribution :
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>
int main()
{
boost::random::mt19937 gen;
boost::random::uniform_real_distribution<> dist(0, 10);
std::map<int, int> hist;
for (int n = 0; n < 10000; ++n) {
++hist[std::floor(dist(gen))];
}
for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
rand()
Si vous devez utiliser rand()
alors nous pouvons aller à la FAQ C pour un guide sur Comment puis-je générer des nombres aléatoires à virgule flottante? , qui donne essentiellement un exemple similaire à celui-ci pour générer un sur l'intervalle [0,1)
:
#include <stdlib.h>
double randZeroToOne()
{
return rand() / (RAND_MAX + 1.);
}
et pour générer un nombre aléatoire dans la plage de [M,N)
:
double randMToN(double M, double N)
{
return M + (rand() / ( RAND_MAX / (N-M) ) ) ;
}