2010-09-19 8 views
2

Ce que j'aimerais faire est de créer une fonction qui prend un paramètre qui est la limite de ce que la génération aléatoire devrait créer. J'ai expérimenté que certains générateurs qui répètent juste le nombre généré encore et encore.créer un nombre aléatoire inférieur à une valeur donnée maximale

Comment puis-je faire un générateur qui ne retourne pas le même nombre de manière consécutive. Quelqu'un peut-il m'aider s'il vous plaît à atteindre mon objectif?

int randomGen(int max) 
{ 
    int n;  
    return n; 
} 
+0

http://www.phanderson.com/C/random.html – miku

+0

http://www.geekpedia.com/tutorial39_Random-Number-Generation.html – miku

+0

http://en.wikipedia.org/wiki/List_of_random_number_generators – pmg

Répondre

1

Que diriez-vous ceci:

int randomGen(int limit) 
{ 
    return rand() % limit; 

} 
    /* ... */ 
int main() 
{ 
    srand(time(NULL)); 
    printf("%d", randomGen(2041)); 

    return 0; 
    } 
+2

Cette méthode courante est incorrecte et donne des nombres aléatoires biaisés sauf si 'limite' est une puissance de 2. –

+0

Simple, et l'OP ne fait aucune mention de la nécessité d'une probabilité ab égale de chaque nombre. –

+0

Il donnera des résultats biaisés même si la limite est une puissance de deux si rand est un générateur linéaire congruentiel. –

0

Sans connaissance explicite du générateur aléatoire de votre plate-forme, ne pas faire rand() % max. Les octets de poids faible des générateurs de nombres aléatoires simples ne sont généralement pas aléatoires.

Utilisez plutôt (retourne un nombre entre mn inclus et max non inclus):

int randomIntegerInRange(int min, int max) 
{ 
    double tmp = (double)rand()/(RAND_MAX - 1.); 
    return min + (int)floor(tmp * (max - min)); 
} 

Mise à jour: La solution est biaisée (voir commentaires pour explication) ci-dessus, et produira probablement pas uniformes . Je ne le supprime pas car c'est un exemple non naturel de quoi ne pas faire. Veuillez utiliser les méthodes de rejet recommandées ailleurs dans ce fil de discussion.

+0

Ne faites pas cela .. –

+0

@Matt: cela fonctionne. Avec d'autres connaissances de rand(), je ferais un module avec une puissance de 2 et un rejet. Mais ici, si rand() est une merde congruente linéaire, il n'y a pas de meilleur moyen. –

+0

Cette solution ne corrige pas le biais. –

0

Tout générateur pseudo-aléatoire répétera les valeurs encore et encore avec une certaine période. C seulement a rand(), si vous utilisez que vous devez initialiser définitivement la graine aléatoire avec srand(). Mais probablement votre plate-forme a mieux que cela.

Sur les systèmes POSIX, vous trouverez toute une famille de fonctions sous la page man drand48. Ils ont une période et une qualité bien définies. Vous trouvez probablement ce dont vous avez besoin, là.

7

La façon la plus simple d'obtenir des résultats uniformément distribués à partir rand est quelque chose comme ceci:

int limited_rand(int limit) 
{ 
    int r, d = RAND_MAX/limit; 
    limit *= d; 
    do { r = rand(); } while (r >= limit); 
    return r/d; 
} 

Le résultat sera dans la gamme 0 à limit-1, et chacun se produira avec une probabilité égale, tant que les valeurs 0 par RAND_MAX tous avaient une probabilité égale avec la fonction originale rand.

D'autres méthodes telles que l'arithmétique modulaire ou la division sans la boucle I utilisée introduisent biais. Les méthodes qui passent par des intermédiaires à virgule flottante n'évitent pas ce problème. Obtenir de bons nombres à virgule flottante aléatoires de rand est au moins aussi difficile. Utiliser ma fonction pour les nombres entiers (ou une amélioration de celle-ci) est un bon point de départ si vous voulez des flottants aléatoires.

Modifier: Voici une explication de ce que je veux dire par biais. Supposons que RAND_MAX est 7 et que limit est 5. Supposons (si c'est une bonne fonction rand) que les sorties 0, 1, 2, ..., 7 soient toutes également probables. Prenant rand()%5 serait mapper 0, 1, 2, 3 et 4 à eux-mêmes, mais les cartes 5, 6 et 7 à 0, 1 et 2. Cela signifie que les valeurs 0, 1 et 2 sont deux fois plus susceptibles de s'afficher comme les valeurs 3 et 4.Un phénomène similaire se produit si vous essayez de redimensionner et de diviser, par exemple en utilisant rand()*(double)limit/(RAND_MAX+1) Ici, 0 et 1 carte à 0, 2 et 3 carte à 1, 4 cartes à 2, 5 et 6 carte à 3, et 7 cartes à 4.

Ces effets sont quelque peu atténués par l'ampleur de RAND_MAX, mais ils peuvent revenir si limit est grand. Par ailleurs, comme d'autres l'ont dit, avec des PRNG à congruence linéaire (l'implémentation typique de rand), les bits faibles ont tendance à se comporter très mal, donc en utilisant l'arithmétique modulaire quand limit est une puissance de 2 peut éviter le problème de biais que j'ai décrit (depuis limit divise généralement RAND_MAX+1 même dans ce cas), mais vous rencontrez un problème différent à sa place.

+0

Bien sûr, si 'limite> RAND_MAX', cela entraînera une division par 0. (Mais c'est peut-être une bonne chose d'attraper les cas où vous n'obtenez pas vraiment des nombres aléatoires de la plage que vous voulez.) – jamesdlin

+0

Oui .. Si cela vous inquiète, vous devriez envelopper 'rand' avec une fonction qui appelle' rand' plusieurs fois et ajoute les bits jusqu'à ce que vous ayez une distribution uniforme sur une large plage fixe de puissance de deux. –

Questions connexes