Nombres aléatoires sur C ++

12

Récemment, je me suis habitué aux langages modernes qui incluent un bon générateur aléatoire de stock, qui est généralement le Twister de Mersenne; maintenant que je suis revenu au C ++, je dois décider quoi utiliser.

J'ai cherché des implémentations de Mersenne Twister et j'ai remarqué qu'il y en a tellement: y en a-t-il une qui est plus utilisée et plus répandue, ou suis-je censé en choisir une en supposant qu'elles sont toutes aussi bonnes?

o0 '.
la source
1
J'aime votre séparation des langages C ++ et modernes.
jcora
2
Peut-être que dire "niveau supérieur" était plus approprié.
o0 '.
Je pense que cette question appartient à stackoverflow
TravisG
5
Sur SO, je donnerais une réponse différente parce que je ne sais pas que c'était pour un moteur de jeu par opposition, disons, aux simulations de Monte Carlo pour les thérapies médicales, auquel cas le fait de ne pas avoir 624 dimensions de hasard peut être mortel.

Réponses:

19

C ++ 11 inclut par défaut un générateur Mersenne Twister dans le cadre de sa nouvelle <random>interface. Par exemple, pour générer uniformément des entiers entre [-10, 10] à l'aide de MT:

std::mt19937 eng; // This is the Mersenne Twister
std:::uniform_int_distribution<int> dist(-10, 10)
for (int i = 0; i < 10; ++i)
    std::cout << dist(eng) << std::endl;

La plupart de ces informations sont également disponibles dans tout compilateur proposant TR1, bien que les noms soient légèrement différents; std::tr1::mt19937et std::tr1::uniform_int<int>.

Je déconseille généralement aux gens d'utiliser Mersenne Twister. C'est un algorithme correct, mais une grande partie de sa popularité n'est que du marketing. La dimension aléatoire de 624 est plus que ce dont la plupart des gens ont besoin, et MT comporte des exigences d'état relativement lourdes et lorsqu'il effectue un recalcul complet de la table, il peut faire sauter le cache. Je suis personnellement partisan de xorshift qui donne d'excellentes périodes et des distributions raisonnables pour tout ce dont un jeu a besoin, avec de minuscules besoins en mémoire et en CPU.

J'ai écrit un générateur xorshift conforme à C ++ 11 (principalement?) - xorshift.hpp , xorshift.cpp - et l' ai placé dans le domaine public. Vous pouvez le brancher dans n'importe quelle fonction de randomisation C ++ 11, comme ci-dessus:

xorshift eng;
std:::uniform_int_distribution<int> dist(-10, 10)
for (int i = 0; i < 10; ++i)
    std::cout << dist(eng) << std::endl;

la source
5
Ouais, c'est le genre de réponse que je cherchais, c'est pourquoi j'ai posté ici sur gamedev:)
o0 '.
1
Je voulais juste noter que rien dans les fichiers que vous avez liés n'indique qu'ils sont dans le domaine public. La façon dont la loi sur le droit d'auteur fonctionne, il doit vraiment y avoir une note claire à ce sujet, car la loi suppose que "tous les droits sont réservés" par défaut. Il est en fait encore plus sûr d'utiliser simplement quelque chose comme la licence MIT ou BSD à 2 clauses, car certaines juridictions ne reconnaissent pas fondamentalement que "cela est dans le domaine public" comme juridiquement contraignant. Si vous souhaitez voir des gens utiliser votre code, cela peut valoir la peine de s'en occuper.
Sean Middleditch
1
@seanmiddleditch: Je suis clair à ce sujet ici. Si vous le souhaitez sous une licence de style MIT, je suivrai l'exemple de SQLite et vous le donnerai pour seulement 1000 $.
L'absence d'un en-tête dans le code déclarant quelque chose (ce que fait SQLite, iirc) est le principal problème. Si vous ne vous en souciez pas, c'est cool. Je viens de vous donner une suggestion amicale.
Sean Middleditch
1

Un autre RNG que j'ai utilisé auparavant à des fins de gamedev est le "petit" RNG de Bob Jenkins, décrit ici .

(Il a également un RNG de force cryptographique appelé ISAAC, mais il est plus grand et plus lent, et les jeux n'ont pas besoin de ce niveau de force.)

Nathan Reed
la source
1
Cela semble plus cher que xorshift (4 xors et 3 décalages vs 4 ajouts, 6 décalages, 2 ors et un xor), a une période pire et court le risque de cycles très courts avec certaines initialisations. Il semble rapide mais pas le plus rapide; période correcte mais loin d'être optimale; mêmes qualités de distribution de base que xorshift; Je ne vois aucune raison de l'utiliser.
C'est suffisant. Je ne connais pas suffisamment l'analyse RNG pour creuser les propriétés de distribution et de cycle.
Nathan Reed