Recherche…


Remarques

En raison des failles de rand() , de nombreuses autres implémentations par défaut sont apparues au fil des ans. Parmi ceux-ci sont:

Génération de nombres aléatoires de base

La fonction rand() peut être utilisée pour générer un nombre entier pseudo-aléatoire compris entre 0 et RAND_MAX ( 0 et RAND_MAX inclus).

srand(int) est utilisé pour générer le générateur de nombres pseudo-aléatoires. Chaque fois que rand() est ensemencé avec la même graine, il doit produire la même séquence de valeurs. Il ne devrait être utilisé qu'une fois avant d'appeler rand() . Elle ne doit pas être répétée de manière répétée ou ré-émise chaque fois que vous souhaitez générer un nouveau lot de nombres pseudo-aléatoires.

La pratique standard consiste à utiliser le résultat du time(NULL) comme graine. Si votre générateur de nombres aléatoires doit avoir une séquence déterministe, vous pouvez affecter le générateur avec la même valeur à chaque démarrage du programme. Ceci n'est généralement pas requis pour le code de version, mais est utile dans les exécutions de débogage pour rendre les bogues reproductibles.

Il est conseillé de toujours semer le générateur, s’il n’est pas ensemencé, il se comporte comme s’il était ensemencé de srand(1) .

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

int main(void) {
    int i;
    srand(time(NULL));
    i = rand();

    printf("Random value between [0, %d]: %d\n", RAND_MAX, i);
    return 0;
}

Sortie possible:

Random value between [0, 2147483647]: 823321433

Remarques:

La norme C ne garantit pas la qualité de la séquence aléatoire produite. Dans le passé, certaines implémentations de rand() avaient de sérieux problèmes de distribution et de caractère aléatoire des nombres générés. L'utilisation de rand() n'est pas recommandée pour les besoins de génération de nombres aléatoires graves, comme la cryptographie.

Génératrice à permutation permutée

Voici un générateur de nombres aléatoires autonome qui ne repose pas sur rand() ou des fonctions de bibliothèque similaires.

Pourquoi voudriez-vous une telle chose? Peut-être que vous ne faites pas confiance au générateur de nombres aléatoires intégré à votre plate-forme, ou peut-être souhaitez-vous une source reproductible de caractère aléatoire indépendante de toute implémentation de bibliothèque particulière.

Ce code est PCG32 de pcg-random.org , un RNG moderne, rapide et polyvalent doté d'excellentes propriétés statistiques. Ce n'est pas cryptographiquement sécurisé, donc ne l'utilisez pas pour la cryptographie.

#include <stdint.h>

/* *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
 * Licensed under Apache License 2.0 (NO WARRANTY, etc. see website) */

typedef struct { uint64_t state;  uint64_t inc; } pcg32_random_t;

uint32_t pcg32_random_r(pcg32_random_t* rng) {
    uint64_t oldstate = rng->state;
    /* Advance internal state */
    rng->state = oldstate * 6364136223846793005ULL + (rng->inc | 1);
    /* Calculate output function (XSH RR), uses old state for max ILP */
    uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
    uint32_t rot = oldstate >> 59u;
    return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}

void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq) {
    rng->state = 0U;
    rng->inc = (initseq << 1u) | 1u;
    pcg32_random_r(rng);
    rng->state += initstate;
    pcg32_random_r(rng);
}

Et voici comment l'appeler:

#include <stdio.h>
int main(void) {
    pcg32_random_t rng; /* RNG state */
    int i;

    /* Seed the RNG */
    pcg32_srandom_r(&rng, 42u, 54u);

    /* Print some random 32-bit integers */
    for (i = 0; i < 6; i++)
        printf("0x%08x\n", pcg32_random_r(&rng));
    
    return 0;
}

Restreindre la génération à une plage donnée

Généralement, lors de la génération de nombres aléatoires, il est utile de générer des nombres entiers compris dans une plage ou une valeur entre 0,0 et 1,0. Bien que le module puisse être utilisé pour réduire la graine à un nombre entier faible, il utilise les bits bas, qui passent souvent par un cycle court, ce qui entraîne un léger déséquilibre de la distribution si N est important par rapport à RAND_MAX.

La macro

#define uniform() (rand() / (RAND_MAX + 1.0))

produit une valeur de 0.0 à 1.0 - epsilon, donc

i = (int)(uniform() * N)

fixera i à un nombre aléatoire uniforme compris entre 0 et N - 1.

Malheureusement, il y a un défaut technique, car RAND_MAX peut être plus grand qu'une variable de type double peut représenter avec précision. Cela signifie que RAND_MAX + 1.0 évalué à RAND_MAX et que la fonction retourne parfois l'unité. C'est peu probable cependant.

Génération Xorshift

Xorshift , une classe de générateurs de nombres pseudo-aléatoires découverts par George Marsaglia , constitue une alternative intéressante aux procédures rand() erronées. Le générateur xorshift fait partie des générateurs de nombres aléatoires non cryptographiquement sécurisés les plus rapides. Plus d'informations et d'autres exemples d'implémentations sont disponibles sur la page Wikipedia de xorshift

Exemple d'implémentation

#include <stdint.h>

/* These state variables must be initialised so that they are not all zero. */
uint32_t w, x, y, z;

uint32_t xorshift128(void) 
{
    uint32_t t = x;
    t ^= t << 11U;
    t ^= t >> 8U;
    x = y; y = z; z = w;
    w ^= w >> 19U;
    w ^= t;
    return w;
}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow