Supposons que vous souhaitiez utiliser les fonctionnalités C ++ <random>
dans un programme pratique (pour une définition de "pratique" - les contraintes font en quelque sorte partie de cette question). Vous avez du code à peu près comme ceci:
int main(int argc, char **argv) {
int seed = get_user_provided_seed_value(argc, argv);
if (seed == 0) seed = std::random_device()();
ENGINE g(seed); // TODO: proper seeding?
go_on_and_use(g);
}
Ma question est, quel type devez-vous utiliser ENGINE
?
J'avais l'habitude de dire toujours
std::mt19937
parce qu'il était rapide à taper et avait une reconnaissance de nom. Mais ces jours-ci, il semble que tout le monde dit que le Mersenne Twister est très lourd et sans cache et ne passe même pas tous les tests statistiques que d'autres font.Je voudrais dire
std::default_random_engine
parce que c'est le "défaut" évident. Mais je ne sais pas si cela varie d'une plateforme à l'autre, et je ne sais pas si c'est statistiquement bon.Puisque tout le monde est sur une plate-forme 64 bits de nos jours, devrions-nous au moins utiliser
std::mt19937_64
Overstd::mt19937
?Je voudrais dire
pcg64
ouxoroshiro128
parce qu'ils semblent bien respectés et légers, mais ils n'existent pas<random>
du tout.Je ne sais rien
minstd_rand
,minstd_rand0
,ranlux24
,knuth_b
, etc. - Ils doivent sûrement être bon pour quelque chose?
De toute évidence, il existe ici des contraintes concurrentes.
Force du moteur. (
<random>
Il n'y a pas de PRNG cryptographiquement solides, mais quand même, certains standardisés sont "plus faibles" que d'autres, non?)sizeof
le moteur.Vitesse de son
operator()
.Facilité d'ensemencement.
mt19937
est notoirement difficile à semer correctement car il a tellement d'état à initialiser.Portabilité entre les fournisseurs de bibliothèques. Si un fournisseur
foo_engine
produit des numéros différents d'un autre fournisseurfoo_engine
, ce n'est pas bon pour certaines applications. (J'espère que cela n'exclut rien sauf peut-êtredefault_random_engine
.)
En pesant toutes ces contraintes du mieux que vous le pouvez, quelle serait, selon vous, la réponse ultime "meilleures pratiques restant dans la bibliothèque standard"? Dois-je continuer à utiliser std::mt19937
, ou quoi?
Réponses:
La référence C ++ répertorie tous les moteurs aléatoires actuellement fournis par C ++. Cependant, la sélection des moteurs laisse beaucoup à désirer (par exemple, voir ma liste de générateurs aléatoires de haute qualité ). Par exemple:
default_random_engine
est défini par l'implémentation, donc on ne sait pas si le moteur présente des failles statistiques dont l'application peut se soucier.linear_congruential_engine
implémente des générateurs congruentiels linéaires. Cependant, ils ont tendance à être de mauvaise qualité à moins que le module ne soit premier et très grand (au moins 64 bits). De plus, ils ne peuvent pas admettre plus de graines que leur module.minstd_rand0
etminstd_rand
admettre seulement environ 2 ^ 31 graines.knuth_b
enveloppe unminstd_rand0
et fait un mélange Bays – Durham de celui-ci.mt19937
etmt19937_64
pourrait admettre beaucoup plus de graines si elles étaient mieux initialisées (par exemple, en initialisant unstd::seed_seq
avec plusieurs sorties derandom_device
, pas une seule), mais elles utilisent environ 2500 octets d'état.ranlux24
etranlux48
utilisent environ 577 bits d'état mais ils sont lents (ils fonctionnent en gardant certains et en rejetant d'autres sorties pseudo-aléatoires).Cependant, C ++ possède également deux moteurs qui enveloppent un autre moteur pour potentiellement améliorer ses propriétés de caractère aléatoire:
discard_block_engine
supprime certaines des sorties d'un moteur aléatoire donné.shuffle_order_engine
implémente un mélange Bays – Durham d'un moteur aléatoire donné.Par exemple, il est possible, par exemple, d'avoir une lecture aléatoire Bays-Durham
mt19937
,ranlux24
ou une coutumelinear_congruential_engine
avecshuffle_order_engine
. Peut-être que le moteur enveloppé est de meilleure qualité que l'original. Cependant, il est difficile de prédire la qualité statistique du nouveau moteur sans le tester .Ainsi, en attendant de tels tests, il semble que ce
mt19937
soit le moteur le plus pratique du standard C ++ pour l'instant. Je connais cependant au moins une proposition visant à ajouter un autre moteur de nombres aléatoires aux futures versions de C ++ (voir le document C ++ P2075 ).la source
Selon C ++ Reference ,
default_random_engine
:Donc, pour une utilisation légère, vous n'avez pas à vous soucier de quoi que ce soit, des graines
default_random_engine
avecEpoch Time (time(0))
et ce serait assez bien;)la source