web-dev-qa-db-fra.com

Générer des nombres aléatoires en C

En cherchant des tutoriels sur la génération de nombres aléatoires en C j'ai trouvé ce sujet

Lorsque j'essaie d'utiliser la fonction Rand() sans paramètres, je reçois toujours 0. Lorsque j'essaie d'utiliser la fonction Rand() avec des paramètres, j'obtiens toujours la valeur 41. Et chaque fois que j'essaie d'utiliser les fonctions arc4random() et random(), j'obtiens une erreur LNK2019 .

Voici ce que j'ai fait:

#include <stdlib.h>
int main()
{
  int x;
  x = Rand(6);
  printf("%d", x);
}

Ce code génère toujours 41. Où vais-je mal? J'utilise Windows XP SP3 et j'utilise l'invite de commande VS2010 comme compilateur.

12
MoonStruckHorrors

Vous devez appeler srand () avant d'appeler Rand pour initialiser le générateur de nombres aléatoires.

Appelez-le avec une graine spécifique et vous obtiendrez toujours la même séquence pseudo-aléatoire

#include <stdlib.h>

int main ()
{
  srand ( 123 );
  int random_number = Rand();
  return 0;
}

ou appelez-le avec une source changeante, c.-à-d. la fonction temps

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

int main ()
{
  srand ( time(NULL) );
  int random_number = Rand();
  return 0;
}

En réponse au commentaire de Moon Rand () génère un nombre aléatoire avec une probabilité égale entre 0 et Rand_MAX (une macro prédéfinie dans stdlib.h).

Vous pouvez ensuite mapper cette valeur sur une plage plus petite, par exemple.

int random_value = Rand(); //between 0 and Rand_MAX

//you can mod the result
int N = 33;
int Rand_capped = random_value % N;  //between 0 and 32
int S = 50;
int Rand_range = Rand_capped + S; //between 50 and 82

//you can convert it to a float
float unit_random = random_value / (float) Rand_MAX; //between 0 and 1 (floating point)

Cela pourrait être suffisant pour la plupart des utilisations, mais il convient de noter que, dans le premier cas, l'opérateur mod introduit un léger biais si N ne se divise pas de manière égale en Rand_MAX + 1.

Les générateurs de nombres aléatoires sont intéressants et complexes, il est largement dit que le générateur Rand () dans la bibliothèque standard C n'est pas un générateur de nombres aléatoires de grande qualité, lisez ( http://en.wikipedia.org/wiki/Random_number_generation pour une définition de la qualité).

http://en.wikipedia.org/wiki/Mersenne_twister (source http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html ) est un générateur populaire de nombres aléatoires de haute qualité.

De plus, je ne connais pas arc4Rand () ou random (), je ne peux donc pas commenter.

31
Akusete

Vous devez ensemencer votre PRNG pour qu'il commence par une valeur différente à chaque fois.

Une simple mais faible qualité seed consiste à utiliser l'heure actuelle:

srand(time(0));

Cela vous aidera à démarrer mais est considéré comme de basse qualité (par exemple, ne l’utilisez pas si vous essayez de générer des clés RSA).

Contexte. Les générateurs de nombres pseudo-aléatoires ne créent pas de véritables séquences de nombres aléatoires, mais les simulent. Étant donné un numéro de point de départ, un PRNG renverra toujours la même séquence de chiffres. Par défaut, ils commencent par le même état interne et renvoient donc la même séquence.

Pour ne pas avoir la même séquence, vous modifiez l'état interne. Le fait de changer l'état interne est appelé "ensemencement". 

5
R Samuel Klatchko

De plus, les PRNG linéaires congruentielles ont tendance à produire plus de caractère aléatoire sur les bits les plus hauts que sur les bits les plus bas. Pour capter le résultat, n'utilisez pas modulo, mais utilisez plutôt quelque chose comme:

j = 1 + (int) (10.0 * (Rand() / (Rand_MAX + 1.0)));

(Celui-ci est tiré de "Recettes numériques en C", ch.7)

3
ninjalj
#include <stdlib.h>

int main()
{
    int x;
    x = Rand(6);
    printf("%d", x);
}

Surtout en tant que débutant, vous devriez demander à votre compilateur d’imprimer tous les avertissements concernant le code défectueux qu’il peut générer. Les compilateurs modernes connaissent de nombreux avertissements qui vous aident à mieux programmer. Par exemple, lorsque vous compilez ce programme avec le compilateur GNU C:

$ gcc -W -Wall Rand.c
Rand.c: In function `main':
Rand.c:5: error: too many arguments to function `Rand'
Rand.c:6: warning: implicit declaration of function `printf'

Vous obtenez deux avertissements ici. Le premier indique que la fonction Rand ne prend aucun argument, pas un comme vous avez essayé. Pour obtenir un nombre aléatoire compris entre 0 et n, vous pouvez utiliser l'expression Rand() % n, qui n'est pas parfaite, mais ok pour les petites n. Les nombres aléatoires qui en résultent ne sont normalement pas répartis de manière égale; les valeurs plus petites sont renvoyées plus souvent.

Le deuxième avertissement vous indique que vous appelez une fonction que le compilateur ne connaît pas à ce stade. Vous devez dire au compilateur en disant #include <stdio.h>. Les fichiers d'inclusion nécessaires pour les fonctions ne sont pas toujours simples, mais demander la spécification Open Group pour les systèmes d'exploitation portables fonctionne dans de nombreux cas: http://www.google.com/search?q=opengroup+Rand .

Ces deux avertissements vous en disent long sur l’historique du langage de programmation C. Il y a 40 ans, la définition d'une fonction n'incluait pas le nombre de paramètres ni les types de paramètres. Il était également correct d'appeler une fonction inconnue, qui fonctionnait dans la plupart des cas. Si vous voulez écrire du code aujourd'hui, vous ne devriez pas vous baser sur ces anciennes fonctionnalités, mais plutôt activer les avertissements de votre compilateur, comprendre les avertissements, puis les corriger correctement.

3
Roland Illig

Vous devez d’abord grainer le générateur car il ne génère pas vrais nombres aléatoires!

Essaye ça:

#include <stdlib.h>
#include <time.h>
int main()
{
    // random seed, time!
    srand( time(NULL) ); // hackish but gets the job done.
    int x;
    x = Rand(); // everytime it is different because the seed is different.
    printf("%d", x);
}
1
AraK

Ou bien, pour obtenir un entier pseudo-aléatoire compris entre 0 et 19, par exemple, vous pouvez utiliser les bits les plus élevés, comme ceci:

j = ((Rand() >> 15) % 20;
1
andy
int *generate_randomnumbers(int start, int end){
    int *res = malloc(sizeof(int)*(end-start));
    srand(time(NULL));
    for (int i= 0; i < (end -start)+1; i++){
        int r = Rand()%end + start;
        int dup = 0;
        for (int j = 0; j < (end -start)+1; j++){
            if (res[j] == r){
                i--;
                dup = 1;
                break;
            }
        }
        if (!dup)
            res[i] = r;
    }
    return res;
}
1
Naveen Tulseela