web-dev-qa-db-fra.com

Quel est le lien entre Srand et la fonction Rand?

Je comprends que la fonction Rand () génère le même numéro chaque fois que vous l’exécutez si vous ne modifiez pas le numéro de départ. C'est là que srand () entre en jeu. Le temps change constamment, je sais donc que vous devez passer le paramètre time (null) à srand. Ma question est avec le code ci-dessous à partir d'un site de tutoriel. 

int main()
{
    int i, n=5;
    time_t t;

    /* Intializes random number generator */
    srand((unsigned) time(&t));

    /* Print 5 random numbers from 0 to 50 */
    for( i = 0 ; i < n ; i++ ) {
        printf("%d\n", Rand() % 50);
    }

    return(0);
}

Je ne vois aucun lien du srand

((unsigned) time(&t)); 

et Rand. 

printf("%d\n", Rand() % 50);

Où est la connexion entre Rand et srand? Ce que je veux dire ou ce que j'attendais, c'est que Rand () obtiendra un paramètre de srand () afin qu'il sache générer différents nombres à chaque fois. Je suppose que cela ressemblerait à Rand (srand (time (null)); 

C'est comme initialiser une variable sans l'utiliser pour moi. Srand est en cours d'initialisation, mais je ne le vois pas utilisé.

Rand génère-t-il des nombres différents parce que srand est appelé avant rand? 

18
Arrow

La graine de nombre aléatoire est une variable statique globale. Rand et srand les deux y ont accès.

21
sqykly

srand() définit la graine utilisée par Rand pour générer des nombres "aléatoires" (entre guillemets car ils sont généralement pseudo-aléatoires). Si vous n'appelez pas srand avant votre premier appel à Rand, c'est comme si vous aviez appelé srand(1) pour définir la valeur de départ à un.

Une grande partie du code utilise l'heure actuelle comme valeur de départ pour que chaque programme exécuté utilise une séquence différente de nombres aléatoires, mais vous pouvez toujours le remplacer par quelque chose comme srand(42) lors du débogage, à des fins de répétabilité. Et l'appel à time() n'a pas réellement besoin une variable pour placer le temps, vous pouvez simplement passer NULL:

srand (time (NULL));

Le tout pourrait être implémenté dans un seul fichier avec quelque chose comme ce qui suit, l'exemple donné dans la norme (ISO C99 7.20.2.2 The srand function).

// Rand_MAX assumed to be 32767.
static unsigned long int next = 1;
void srand(unsigned int seed) { next = seed; }
int Rand(void) {
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}

Le fait que next soit une variable statique en haut du fichier signifie qu'il est invisible pour tout ce qui se trouve en dehors du fichier, mais visible pour tout ce qu'il contient (en quelque sorte un global localisé). C'est la méthode de communication entre srand() et Rand().

13
paxdiablo

Vous ne voyez pas de lien parce que (heureusement!) Celui qui a conçu Rand() a décidé de conserver ce détail de la mise en œuvre, de la même manière que vous ne voyez pas le contenu d'une FILE de stdio; l'inconvénient est qu'ils ont décidé de faire de cet état une variable globale (mais cachée) plutôt qu'un paramètre du générateur.

Contrastez cela avec la Rand_r() obsolète: l'état est un entier non signé (supposé être> = 32 bits), ce qui signifie que même s'il est interdit d'utiliser un meilleur générateur dont l'état est supérieur, simplement parce qu'il n'y a pas de place pour le stocker!

En gardant caché l'état interne, on est libre de choisir l'algorithme qui fonctionne le mieux (vitesse, période, ...) et de l'utiliser en coulisse, à condition de garantir que l'appel de Rand sans initialisation équivaut à l'appel de srand avec graine == 1.

Paxdiablo vous a montré l'exemple de la norme C; voir par exemple http://en.wikipedia.org/wiki/Multiply-with-carry pour un exemple utilisant un générateur différent que vous pourriez cacher derrière Rand/srand.

Pour être très clair: si Rand_r avait été conçu correctement, il y aurait un type opaque, par exemple Rand_t (qui pourrait être un entier, une structure, un tableau, ...), que vous passeriez à Rand_r et à certains hypotétique srand_r, comme dans

Rand_t state;
srand_r(&state, 1);
n = Rand_r(&state);

La fonction Rand est exactement comme ceci, sauf qu’il n’ya qu’une variable state.

4
loreb

Rand vous donne une séquence pseudo aléatoire de nombres.

Ce numéro est généré par un algorithme qui renvoie une séquence de nombres apparemment non liés à chaque appel. Cet algorithme utilise une graine pour générer la série, qui doit être initialisée à une valeur distinctive à l'aide de la fonction srand. 

srand à chaque appel place le pointeur à un emplacement de la liste dans lequel vous vous inscrivez. Si vous ne l'appelez pas à chaque tentative ou ne lui donnez pas une graine fixe, la même séquence vous sera donnée. Tant de gens suggèrent de donner la seconde actuelle comme graine. Mais si vous essayez d'exécuter votre code deux fois dans la même seconde, il vous donnera la même séquence.

Pour chaque valeur de départ différente utilisée dans un appel à srand, on peut s’attendre à ce que le générateur de nombres pseudo-aléatoires génère une succession de résultats différente lors des appels suivants à Rand pour plus d'explications

0
Jimit Rupani