2017-04-15 1 views
2

Selon: http://www.cplusplus.com/reference/cstdlib/rand/Alternative à rand() pour éviter les conditions de course?

En C, l'algorithme de génération utilisé par rand est garanti seulement être avancés par les appels à cette fonction. En C++, cette contrainte est relâchée, et une implémentation de bibliothèque est autorisée à avancer le générateur dans d'autres circonstances (telles que les appels aux éléments de ).

Mais ici il dit:

La fonction accède et modifie les objets d'état internes, qui peuvent causer des courses de données avec des appels simultanés à rand ou srand.

Certaines bibliothèques offrent une fonction alternative qui évite explicitement ce type de course de données: rand_r (non-portable).

Les implémentations de bibliothèques C++ sont autorisées à garantir qu'aucune race de données pour n'appelle cette fonction.

Idéalement je voudrais avoir une sorte de « instance » de rand, de sorte que pour cette instance, et une graine donnée, je produis toujours la même séquence de numéros pour les appels à cette instance . Avec les versions actuelles, il semble que sur certaines plateformes, les appels par d'autres fonctions à rand() (peut-être même sur des threads différents), pourraient affecter la séquence des nombres générés dans mon thread par mon code. Y at-il une alternative, où je peux conserver une sorte d '"instance", où je suis sûr de générer une séquence particulière, étant donné une graine, et où d'autres appels à différentes "instances" ne l'affectent pas?

EDIT: Pour plus de clarté - mon code va fonctionner sur plusieurs plateformes différentes (iOS, Android, Windows 8.1, Windows 10, Linux, etc.), et il m'est impossible de tester toutes les implémentations actuellement. Je voudrais juste mettre en œuvre des choses basées sur ce qui est garanti par la norme ...

+2

Découvrez les fonctions de nombres aléatoires C++ 11: http://en.cppreference.com/w/cpp/numeric/random – aschepler

+0

@aschepler Je me fiche de savoir à quel point les nombres sont "aléatoires". Il y a tellement de moteurs différents que ça va prendre beaucoup de temps pour savoir lequel fait ce que je demande dans la question .. –

+1

D'accord, mais la nouvelle façon vous permet de stocker tout l'état que vous voulez, plutôt que de compter sur un état global. – aschepler

Répondre

5

Vous pouvez utiliser std::uniform_int_distribution et std::mt19937 pour maintenir un générateur avec votre semence commune (tous de <random> bibliothèque).

std::mt19937 gen(SEED); 
std::uniform_int_distribution<> dis(MIN, MAX); 
auto random_number = dis(gen); 

Ici, SEED est le numéro de départ que vous souhaitez spécifier.Vous pouvez définir une autre graine plus tard avec la méthode .seed aussi:

std::mt19937 gen{}; 
gen.seed(SEED); 

Si vous avez besoin pour générer un, vous pouvez utiliser std::random_device pour que:

std::random_device rd{}; 
std::mt19937 gen(rd()); 

La partie dis(MIN, MAX) définit une gamme de min et max valeurs que cette distribution peut atteindre, ce qui signifie qu'elle ne générera jamais une valeur supérieure à MAX ou inférieure à MIN. Enfin, vous pouvez utiliser votre générateur avec cette distribution pour générer les valeurs aléatoires souhaitées comme suit: dis(gen). La distribution peut prendre n'importe quel générateur, donc si vous voulez d'autres distributions avec la même séquence de nombres aléatoires, vous pouvez faire une copie de gen, ou utiliser la même graine et construire deux ou plusieurs générateurs.

+0

Est-ce que cette partie de STL? –

+0

@KaizerSozay, oui, c'est à partir de la bibliothèque C++ standard. –

+0

Dis, et gen sont-ils complètement indépendants des autres instances de std :: mt19937 et std :: uniform_int_distribution? Je ne pouvais pas le trouver dans la documentation à laquelle vous étiez lié ... –

1
+0

La sécurité n'est pas importante pour mon but. Pouvez-vous expliquer pourquoi le hasard est meilleur? Puis-je le semer et obtenir la même séquence? –

+0

random() ne fait pas partie de STL .. y a-t-il quelque chose dans STL que vous recommandez? –