web-dev-qa-db-fra.com

Pourquoi ai-je toujours la même séquence de nombres aléatoires avec Rand ()?

C'est la première fois que j'essaie des nombres aléatoires avec C (je manque de C #). Voici mon code:

int i, j = 0;
for(i = 0; i <= 10; i++) {
    j = Rand();
    printf("j = %d\n", j);
}

avec ce code, je reçois la même séquence à chaque fois que je lance le code. Mais cela génère différentes séquences aléatoires si j'ajoute srand(/*somevalue/*) avant la boucle for. Quelqu'un peut-il expliquer pourquoi?

48
Hannoun Yassir

Vous devez le semer. Le semer avec le temps est une bonne idée:

srand()

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main ()
{
  srand ( time(NULL) );
  printf ("Random Number: %d\n", Rand() %100);
  return 0;
}

Vous obtenez la même séquence car Rand() est automatiquement associé à la valeur 1 si vous n'appelez pas srand().

Modifier

En raison de commentaires

Rand() retournera un nombre compris entre 0 et Rand_MAX (défini dans la bibliothèque standard). L'utilisation de l'opérateur modulo (%) donne le reste de la division Rand() / 100. Cela forcera le nombre aléatoire à se situer dans la plage 0-99. Par exemple, pour obtenir un nombre aléatoire compris entre 0 et 999, nous appliquerions Rand() % 1000.

80
kjfletch

Rand () renvoie pseudo-aléatoire nombres. Il génère des nombres basés sur un algorithme donné ..__ Le point de départ de cet algorithme est toujours le même, vous verrez donc la même séquence générée pour chaque invocation. C'est pratique lorsque vous devez vérifier le comportement et la cohérence de votre programme.

Vous pouvez définir le "germe" du générateur aléatoire avec la fonction srand (appeler seulement srand une fois dans un programme). Un moyen courant d'obtenir différentes séquences à partir du générateur Rand () consiste à définir le heure actuelle ou l'id du processus:

srand (time (NULL)); ou srand (getpid ()); au début du programme.

Générer de véritables aléas est très difficile pour un ordinateur, mais pour un travail pratique non lié à la crypto, un algorithme qui tente de répartir uniformément les séquences générées fonctionne bien.

33
nos

Pour citer de man Rand :

La fonction srand () définit son argument comme graine pour une nouvelle séquence de nombres entiers pseudo-aléatoires à renvoyer par Rand (). Ces séquences sont répétable en appelant srand () avec le même valeur de départ.

Si aucune valeur de départ n'est fournie, le La fonction Rand () est automatiquement ensemencé avec une valeur de 1.

Donc, en l'absence de valeur de départ, Rand() suppose que la valeur de départ est 1 (chaque fois dans votre cas) et avec la même valeur de départ, Rand() produira la même séquence de nombres.

19
Aditya Sehgal

Il y a beaucoup de réponses ici, mais personne ne semble avoir vraiment expliqué pourquoi Rand () génère toujours la même séquence avec la même graine - ou même ce que fait réellement la graine. Alors voilà.

La fonction Rand () maintient un état interne. Conceptuellement, vous pourriez considérer cela comme une variable globale d'un type appelé Rand_state. Chaque fois que vous appelez Rand (), cela fait deux choses. Il utilise l'état existant pour calculer un nouvel état et utilise le nouvel état pour calculer un nombre à vous renvoyer:

state_t Rand_state = INITIAL_STATE;

state_t calculate_next_state(state_t s);
int calculate_return_value(state_t s);

int Rand(void)
{
    Rand_state = calculate_next_state(Rand_state);
    return calculate_return_value(Rand_state);
}

Vous pouvez maintenant voir que chaque fois que vous appelez Rand (), cela va faire passer Rand_state d'un pas le long d'un chemin prédéterminé. Les valeurs aléatoires que vous voyez sont simplement basées sur votre position sur ce chemin, elles vont donc suivre également une séquence prédéterminée.

Maintenant, voici où srand () entre en jeu. Il vous permet de sauter à un point différent du chemin:

state_t generate_random_state(unsigned int seed);

void srand(unsigned int seed)
{
    Rand_state = generate_random_state(seed);
}

Les détails exacts de state_t, Calculate_next_state (), Calculate_return_value () et generate_random_state () peuvent varier d'une plate-forme à l'autre, mais ils sont généralement assez simples.

Vous pouvez voir que chaque fois que votre programme démarre, Rand_state va démarrer à INITIAL_STATE (ce qui équivaut à generate_random_state (1)) - c'est pourquoi vous obtenez toujours la même séquence si vous n'utilisez pas srand ().

11
caf

Si je me souviens de la citation de l'ouvrage fondamental de Knuth "L'art de la programmation informatique" au début du chapitre sur la génération de nombres aléatoires, voici ce qui se passe:

"Quiconque tente de générer des nombres aléatoires par des moyens mathématiques est, techniquement, en état de péché".

En termes simples, les générateurs de nombres aléatoires sont des algorithmes mathématiques et prévisibles à 100%. C’est en fait une bonne chose dans de nombreuses situations, où une séquence répétable de nombres "aléatoires" est souhaitable - par exemple pour certains exercices statistiques, où vous ne souhaitez pas que les résultats "aléatoires" soient introduits par des données réellement aléatoires introduites grâce à effets de regroupement.

La deuxième solution populaire consiste à récupérer des bits de données "aléatoires" à partir du matériel de l'ordinateur, mais ce n'est pas vraiment aléatoire non plus - bien que l'environnement d'exploitation soit complexe, plus il existe de possibilités pour le caractère aléatoire - ou du moins l'imprévisibilité.

Les générateurs de données vraiment aléatoires ont tendance à se tourner vers des sources extérieures. La désintégration radioactive est un favori, tout comme le comportement des quasars. Tout ce qui trouve ses racines dans les effets quantiques est effectivement aléatoire, ce qui est très ennuyeux pour Einstein.

9
Tim H

Les générateurs de nombres aléatoires ne sont pas réellement aléatoires, ils aiment bien que la plupart des logiciels soient complètement prévisibles. Ce que fait Rand, c'est créer un nombre pseudo-aléatoire différent à chaque fois qu'il s'appelle Un qui semble être aléatoire. Pour l'utiliser correctement, vous devez lui donner un point de départ différent. 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main ()
{
  /* initialize random seed: */
  srand ( time(NULL) );

  printf("random number %d\n",Rand());
  printf("random number %d\n",Rand());
  printf("random number %d\n",Rand());
  printf("random number %d\n",Rand());

  return 0;
}
7
Howard May

Ceci est de http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.13.html#Rand :

Déclaration:

void srand(unsigned int seed); 

Cette fonction génère le générateur de nombres aléatoires utilisé par la fonction Rand. Si vous semez un srand avec la même graine, Rand retournera la même séquence de nombres pseudo-aléatoires. Si srand n'est pas appelé, Rand agit comme si srand (1) avait été appelé.

2
Key

Rand () renvoie le nombre aléatoire (pseudo) suivant dans une série. Qu'est-ce qui se passe est que vous avez la même série à chaque fois son exécution (par défaut «1»). Pour créer une nouvelle série, vous devez appeler srand () avant d'appeler Rand ().

Si vous voulez quelque chose de aléatoire à chaque fois, vous pouvez essayer:

srand (time (0));
2
Chet

Aucun de vous ne répond à sa question. 

avec ce code, je reçois la même séquence à chaque fois que le code, mais il génère des séquences aléatoires si j'ajoute srand (/ somevalue /) avant la boucle for. quelqu'un peut-il expliquer pourquoi?

D'après ce que mon professeur m'a dit, il est utilisé si vous voulez vous assurer que votre code fonctionne correctement et voir s'il y a quelque chose qui ne va pas ou si vous pouvez changer quelque chose.

0
James

appelez srand(sameSeed) avant d'appeler Rand(). Plus de détails ici .

0
dfa

Semer la Rand()

void srand (unsigned int seed)

Cette fonction établit une graine en tant que graine pour une nouvelle série de nombres pseudo-aléatoires. Si vous appelez Rand avant qu'une graine ait été établie avec srand, la valeur 1 est utilisée comme graine par défaut. 

Pour produire une série pseudo-aléatoire différente chaque fois que votre programme est exécuté, effectuez une étape (heure (0)).

0
nik