créer un nombre aléatoire inférieur à une valeur donnée max

Ce que j’aimerais faire est de créer une fonction qui prend un paramètre qui est la limite du nombre que la génération aléatoire doit créer. J’ai constaté que certains générateurs ne faisaient que répéter le nombre généré maintes et maintes fois.

Comment puis-je faire un générateur qui ne retourne pas le même nombre consécutivement. Quelqu’un peut-il m’aider s’il vous plaît à atteindre mon objective?

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

Le moyen le plus simple d’obtenir des résultats uniformément répartis à partir de rand est le suivant:

 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 compris entre 0 limit-1 , et chacun se produira avec une probabilité égale, à condition que les valeurs de 0 à RAND_MAX toutes la même probabilité avec la fonction rand origine.

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

Edit : Voici une explication de ce que je veux dire par partialité. Supposons que RAND_MAX soit RAND_MAX 7 et que la limit soit RAND_MAX 5. Supposons (s’il s’agit d’une bonne fonction rand ) que les sorties 0, 1, 2, …, 7 ont toutes les mêmes chances. Si vous rand()%5 mappera 0, 1, 2, 3 et 4 sur eux-mêmes, mais mappera 5, 6 et 7 sur 0, 1 et 2. Cela signifie que les valeurs 0, 1 et 2 sont deux fois plus importantes. susceptibles de s’afficher sous 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 correspondent à 0, 2 et 3 cartes à 1, 4 cartes à 2, 5 et 6 cartes à 3 et 7 cartes à 4.

Ces effets sont quelque peu atténués par l’ampleur de RAND_MAX , mais ils peuvent revenir si la limit est grande. Par ailleurs, comme d’autres l’ont déjà dit, avec les PRNG à congruence linéaire (l’implémentation typique de rand ), les bits faibles tendent à se comporter très mal, aussi l’utilisation de l’arithmétique modulaire lorsque la limit est de 2 peut éviter le problème de biais décrit plus haut. limit divise généralement RAND_MAX+1 manière égale dans ce cas), mais vous rencontrez un problème différent à la place.

Que dis-tu de ça:

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

Tout générateur pseudo-aléatoire répétera les valeurs encore et encore avec une certaine période. C n’a que rand() , si vous utilisez cela, 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, il existe toute une famille de fonctions que vous devriez trouver sous la page man drand48 . Ils ont une période et une qualité bien définies. Vous trouverez probablement ce dont vous avez besoin, là-bas.

Sans une connaissance explicite du générateur aléatoire de votre plate-forme, ne faites pas 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 à la place (retourne un nombre compris entre min 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 ci-dessus est biaisée (voir les commentaires pour une explication) et ne produira probablement pas de résultats uniformes. Je ne le supprime pas car c’est un exemple non naturel de ce qu’il ne faut pas faire . Veuillez utiliser les méthodes de rejet recommandées ailleurs dans ce fil.