La fonction rand () en C n’est pas aléatoire, même si elle est ensemencée

Il s’agit probablement d’un problème lié à la machine, mais je ne peux pas comprendre ce qui pourrait ne pas être correct.

#include  #include  #include  int main(int argc, char** argv) { srand(time(NULL)); int r1 = rand(); int r2 = rand(); printf("%d %d\n", r1, r2); } 

Je comstack le code ci-dessus en utilisant

 gcc randd.c 

Ensuite, exécutez-le plusieurs fois manuellement et les premiers nombres semblent incroyablement similaires, tandis que les seconds semblent aléatoires:

 1025720610 1435057801 1025737417 1717533050 1025754224 2000008299 1025771031 134999901 1025787838 417475150 

Ce premier appel à rand() semble fortement corrélé au temps et augmente ssortingctement au fil du temps. Des idées quant à pourquoi cela se produit ou comment le résoudre?

Cela se produit sur OSX 10.11

  1. rand() est assez mauvais, évitez-le si possible. Dans tout bon GNA, les premières valeurs seront impossibles à distinguer du hasard, même lorsque la graine est proche (distance de Hamming). En rand ce n’est pas le cas.
  2. Si vous devez utiliser rand, mettez-le en grappe, de préférence avec une entropie plus élevée que le temps, et appelez rand() plusieurs fois au lieu de ré-ensemencer-en-appelant.

Par exemple de 2, considérons:

 #include  #include  #include  int main(int argc, char** argv) { int t=time(NULL); srand(t); for(int i=0; i < 10; i++) { float r = (float)rand()/(float)(RAND_MAX); printf("%f\n", r); } } 

Avec le résultat:

 0.460600 0.310486 0.339473 0.519799 0.258825 0.072276 0.749423 0.552250 0.665374 0.939103 

C'est toujours un mauvais RNG mais au moins, la plage est meilleure lorsque vous lui permettez d'utiliser l'état interne au lieu de lui donner une autre graine similaire.

C’est exactement ce à quoi vous devez vous attendre. Il n’y a pas une telle chose comme “un nombre aléatoire”. Il n’y a que des séquences de nombres avec une dissortingbution aléatoire. La fonction rand() génère de telles séquences, mais vous ne lui en donnez pas la chance, car vous continuez à la ré-ensemencer. Le premier nombre généré par rand() peut très bien être une simple fonction de la graine, ou de la graine elle-même. Certaines fonctions de rand() peuvent hacher le germe pour cacher cela, mais cela ne les améliore pas vraiment, car le contrat de rand() consiste à produire une séquence aléatoire.

Si vous avez besoin d’une séquence de nombres aléatoires qui survit en exécutant plusieurs programmes, vous devrez faire quelque chose comme: (a) Ecrivez un programme qui appelle srand() une fois, puis plusieurs fois avec rand() , puis demandez à vos autres programmes nombres aléatoires de ce programme sur IPC; (b) Utilisez quelque chose comme /dev/urandom ; (c) Utilisez quelque chose comme random.org .