J'ai besoin de générer des nombres aléatoires dans un intervalle spécifié, [max; min].
En outre, les nombres aléatoires doivent être uniformément répartis sur l'intervalle, non situés à un point particulier.
Actuellement, je génère comme:
for(int i=0; i<6; i++)
{
DWORD random = rand()%(max-min+1) + min;
}
À partir de mes tests, des nombres aléatoires sont générés autour d'un seul point.
Example
min = 3604607;
max = 7654607;
Nombres aléatoires générés:
3631594
3609293
3630000
3628441
3636376
3621404
À partir des réponses ci-dessous: OK, RAND_MAX est 32767. Je suis sur la plate-forme Windows C ++. Existe-t-il une autre méthode pour générer des nombres aléatoires avec une distribution uniforme?
rand()
était uniforme. Quelle bibliothèque utilisez-vous?cstdlib.h
'srand()
n'est PAS uniforme: cplusplus.com/reference/cstdlib/randRéponses:
Pourquoi
rand
une mauvaise idéeLa plupart des réponses que vous avez obtenues ici utilisent la
rand
fonction et l'opérateur de module. Cette méthode peut ne pas générer des nombres de manière uniforme (elle dépend de la plage et de la valeur deRAND_MAX
), et est donc déconseillée.C ++ 11 et génération sur une plage
Avec C ++ 11, plusieurs autres options ont vu le jour. L' un qui correspond à vos besoins, pour générer un nombre aléatoire dans une gamme, très bien:
std::uniform_int_distribution
. Voici un exemple:Et voici l 'exemple en cours.
Autres générateurs aléatoires
L'en-
<random>
tête offre d'innombrables autres générateurs de nombres aléatoires avec différents types de distributions, y compris Bernoulli, Poisson et normal.Comment puis-je mélanger un conteneur?
La norme prévoit
std::shuffle
, qui peut être utilisée comme suit:L'algorithme réorganisera les éléments de manière aléatoire, avec une complexité linéaire.
Boost.Random
Une autre alternative, au cas où vous n'auriez pas accès à un compilateur C ++ 11 +, est d'utiliser Boost.Random . Son interface est très similaire à celle du C ++ 11.
la source
mt19937
type?1 9 6 2 8 7 1 4 7 7
. Savez-vous comment randomiser cela chaque fois que nous exécutons le programme?[modifier] Attention: ne pas utiliser
rand()
pour les statistiques, la simulation, la cryptographie ou quoi que ce soit de sérieux.C'est assez bon pour que les nombres semblent aléatoires pour un humain typique pressé, pas plus.
Voir la réponse de @ Jefffrey pour de meilleures options, ou cette réponse pour les nombres aléatoires crypto-sécurisés.
En général, les bits hauts montrent une meilleure distribution que les bits bas, donc la manière recommandée pour générer des nombres aléatoires d'une plage à des fins simples est:
Remarque : assurez-vous que RAND_MAX + 1 ne déborde pas (merci Demi)!
La division génère un nombre aléatoire dans l'intervalle [0, 1); "étirez" ceci à la plage requise. Ce n'est que lorsque max-min + 1 se rapproche de RAND_MAX que vous avez besoin d'une fonction "BigRand ()" comme celle publiée par Mark Ransom.
Cela évite également certains problèmes de découpage dus au modulo, qui peuvent aggraver encore plus vos chiffres.
Le générateur de nombres aléatoires intégré n'a pas la garantie d'avoir la qualité requise pour les simulations statistiques. Il est normal que les nombres «semblent aléatoires» pour un humain, mais pour une application sérieuse, vous devriez prendre quelque chose de mieux - ou au moins vérifier ses propriétés (une distribution uniforme est généralement bonne, mais les valeurs ont tendance à être corrélées et la séquence est déterministe ). Knuth a un excellent traité (quoique difficile à lire) sur les générateurs de nombres aléatoires, et j'ai récemment trouvé que LFSR était excellent et très simple à mettre en œuvre, étant donné que ses propriétés sont bonnes pour vous.
la source
( rand() / ((double)RAND_MAX+1)) * (max-min+1) + min
déplacer simplement la conversion pour doubler et éviter le problème.Je voudrais compléter les excellentes réponses de Angry Shoe et Peterchen par un bref aperçu de l'état de l'art en 2015:
Quelques bons choix
randutils
La
randutils
bibliothèque (présentation) est une nouveauté intéressante, offrant une interface simple et des capacités aléatoires robustes (déclarées). Il présente l'inconvénient d'ajouter une dépendance à votre projet et, étant nouveau, il n'a pas été testé de manière approfondie. Quoi qu'il en soit, étant gratuit (licence MIT) et en-tête uniquement, je pense que cela vaut la peine d'essayer.Échantillon minimal: un jet de dé
Même si l'on n'est pas intéressé par la bibliothèque, le site ( http://www.pcg-random.org/ ) propose de nombreux articles intéressants sur le thème de la génération de nombres aléatoires en général et de la bibliothèque C ++ en particulier.
Boost.Random
Boost.Random
(documentation) est la bibliothèque qui a inspiréC++11
les<random>
, avec qui partage une grande partie de l'interface. Tout en étant théoriquement une dépendance externe, elleBoost
a désormais le statut de bibliothèque «quasi-standard», et sonRandom
module pourrait être considéré comme le choix classique pour la génération de nombres aléatoires de bonne qualité. Il présente deux avantages par rapport à laC++11
solution:random_device
utilise des méthodes spécifiques au système pour offrir un semis de bonne qualitéLe seul petit défaut est que l'offre de module
random_device
n'est pas uniquement en-tête, il faut compiler et lierboost_random
.Échantillon minimal: un jet de dé
Bien que l'échantillon minimal fasse bien son travail, les vrais programmes devraient utiliser une paire d'améliorations:
mt19937
unthread_local
: le générateur est assez dodu (> 2 Ko) et vaut mieux ne pas être alloué sur la pilemt19937
avec plus d'un entier: le Mersenne Twister a un grand état et peut bénéficier de plus d'entropie lors de l'initialisationQuelques choix pas si bons
La bibliothèque C ++ 11
Tout en étant la solution la plus idiomatique, la
<random>
bibliothèque n'offre pas grand-chose en échange de la complexité de son interface même pour les besoins de base. Le défaut est làstd::random_device
: le Standard n'impose aucune qualité minimale pour sa sortie (tant que lesentropy()
retours0
) et, à partir de 2015, MinGW (pas le compilateur le plus utilisé, mais pas un choix ésotérique) imprimera toujours4
sur l'échantillon minimal.Échantillon minimal: un jet de dé
Si l'implémentation n'est pas pourrie, cette solution devrait être équivalente à celle de Boost, et les mêmes suggestions s'appliquent.
La solution de Godot
Échantillon minimal: un jet de dé
C'est une solution simple, efficace et soignée. Seul défaut, la compilation prendra un certain temps - environ deux ans, à condition que C ++ 17 soit publié à temps et que la
randint
fonction expérimentale soit approuvée dans le nouveau Standard. Peut-être que d'ici là aussi les garanties sur la qualité des semis s'amélioreront.La solution pire-est-meilleure
Échantillon minimal: un jet de dé
L'ancienne solution C est considérée comme nuisible, et pour de bonnes raisons (voir les autres réponses ici ou cette analyse détaillée ). Pourtant, il a ses avantages: c'est simple, portable, rapide et honnête, dans le sens où on sait que les nombres aléatoires que l'on obtient ne sont guère décents, et donc on n'est pas tenté de les utiliser à des fins sérieuses.
La solution de troll comptable
Échantillon minimal: un jet de dé
Bien que 9 soit un résultat quelque peu inhabituel pour un jet de dé régulier, il faut admirer l'excellente combinaison de bonnes qualités de cette solution, qui parvient à être la plus rapide, la plus simple, la plus conviviale et la plus portable. En remplaçant 9 par 4, on obtient un générateur parfait pour tout type de dé Donjons et Dragons, tout en évitant les valeurs chargées de symboles 1, 2 et 3. Le seul petit défaut est que, à cause de la mauvaise humeur des trolls comptables de Dilbert, ce programme engendre en fait un comportement indéfini.
la source
randutils
bibliothèque s'appelle maintenant PCG.Si
RAND_MAX
est 32767, vous pouvez facilement doubler le nombre de bits.la source
rand
appel revient0x1234
et le second0x5678
, alors vous obtenez0x12345678
. C'est le seul numéro que vous pouvez obtenir qui commence par0x1234
, car le numéro suivant le sera toujours0x5678
. Vous obtenez des résultats 32 bits, mais vous n'avez que 32768 numéros possibles.Si vous le pouvez, utilisez Boost . J'ai eu de la chance avec leur bibliothèque aléatoire .
uniform_int
devrait faire ce que vous voulez.la source
uniform_int
époque. Il est assez facile de générer une sortie impartiale, il y a eu plusieurs questions ici qui démontrent la méthode.Si vous êtes préoccupé par le caractère aléatoire et non par la vitesse, vous devez utiliser une méthode de génération de nombres aléatoires sécurisée. Il y a plusieurs façons de faire cela ... La plus simple étant d'utiliser le générateur de nombres aléatoires d'OpenSSL .
Vous pouvez également écrire le vôtre à l'aide d'un algorithme de chiffrement (comme AES ). En choisissant une graine et un IV , puis en rechiffrant en continu la sortie de la fonction de cryptage. Utiliser OpenSSL est plus simple, mais moins viril.
la source
Vous devriez rechercher
RAND_MAX
votre compilateur / environnement particulier. Je pense que vous verriez ces résultats si vousrand()
produisez un nombre aléatoire de 16 bits. (vous semblez supposer que ce sera un nombre de 32 bits).Je ne peux pas promettre que ce soit la réponse, mais veuillez indiquer votre valeur
RAND_MAX
et un peu plus de détails sur votre environnement.la source
Vérifiez quoi
RAND_MAX
y a sur votre système - je suppose qu'il ne s'agit que de 16 bits et que votre plage est trop grande pour cela.Au-delà de cela, voir cette discussion sur: Générer des nombres entiers aléatoires dans une plage désirée et les notes sur l'utilisation (ou non) de la fonction C rand () .
la source
Ce n'est pas le code, mais cette logique peut vous aider.
la source
Si vous voulez que les nombres soient uniformément répartis sur la plage, vous devez diviser votre plage en un nombre de sections égales qui représentent le nombre de points dont vous avez besoin. Ensuite, obtenez un nombre aléatoire avec un min / max pour chaque section.
En outre, vous ne devriez probablement pas l'utiliser
rand()
car ce n'est pas très bon pour générer des nombres aléatoires. Je ne sais pas sur quelle plate-forme vous utilisez, mais il existe probablement une meilleure fonction que vous pouvez appelerrandom()
.la source
Cela devrait fournir une distribution uniforme sur la plage
[low, high)
sans utiliser de flotteurs, tant que la plage globale est inférieure à RAND_MAX.et pour les valeurs supérieures à RAND_MAX, vous voulez quelque chose comme
C'est à peu près comment std :: uniform_int_distribution fait les choses.
la source
De par leur nature, un petit échantillon de nombres aléatoires n'a pas à être uniformément distribué. Ils sont aléatoires, après tout. Je conviens que si un générateur de nombres aléatoires génère des nombres qui semblent systématiquement groupés, alors il y a probablement quelque chose qui ne va pas.
Mais gardez à l'esprit que le hasard n'est pas nécessairement uniforme.
Edit: j'ai ajouté "petit échantillon" pour clarifier.
la source
La solution donnée par man 3 rand pour un nombre compris entre 1 et 10 inclus est:
Dans votre cas, ce serait:
Bien sûr, ce n'est pas un hasard ou une uniformité parfaits comme le soulignent certains autres messages, mais cela suffit dans la plupart des cas.
la source
@Solution
((double) rand() / (RAND_MAX+1)) * (max-min+1) + min
Attention : N'oubliez pas qu'en raison de l'étirement et des erreurs de précision possibles (même si RAND_MAX était suffisamment grand), vous ne pourrez générer que des «bins» uniformément répartis et pas tous les nombres en [min, max].
@Solution: Bigrand
Attention : notez que cela double les bits, mais ne sera toujours pas capable de générer tous les nombres de votre plage en général, c'est-à-dire qu'il n'est pas forcément vrai que BigRand () générera tous les nombres entre dans sa plage.
Info : Votre approche (modulo) est "fine" tant que la plage de rand () dépasse votre plage d'intervalle et que rand () est "uniforme". L'erreur pour au plus les premiers nombres max - min est 1 / (RAND_MAX +1).
Aussi, je suggère de passer au nouveau package aléatoire e en C ++ 11, qui offre de meilleures et plus de variétés d'implémentations que rand ().
la source
Voici la solution que j'ai trouvée:
Il s'agit d'une solution de compartiment, conceptuellement similaire aux solutions utilisées
rand() / RAND_MAX
pour obtenir une plage de virgule flottante entre 0-1, puis arrondir cela dans un compartiment. Cependant, il utilise des calculs purement entiers et tire parti du plancher de division entière pour arrondir la valeur au compartiment le plus proche.Il fait quelques hypothèses. Premièrement, il suppose que cela
RAND_MAX * (max - min + 1)
rentrera toujours dans un fichierint32_t
. Si desRAND_MAX
calculs int 32767 et 32 bits sont utilisés, la plage maximale que vous pouvez avoir est 32767. Si votre implémentation a un RAND_MAX beaucoup plus grand, vous pouvez surmonter ce problème en utilisant un entier plus grand (commeint64_t
) pour le calcul. Deuxièmement, siint64_t
est utilisé maisRAND_MAX
est toujours 32767, à des plages plus grandes queRAND_MAX
vous commencerez à avoir des "trous" dans les nombres de sortie possibles. C'est probablement le plus gros problème avec toute solution dérivée de la mise à l'échellerand()
.Des tests sur un grand nombre d'itérations montrent néanmoins que cette méthode est très uniforme pour les petites plages. Cependant, il est possible (et probable) que, mathématiquement, cela présente un léger biais et développe éventuellement des problèmes lorsque la gamme approche
RAND_MAX
. Testez-le par vous-même et décidez s'il répond à vos besoins.la source
Bien sûr, le code suivant ne vous donnera pas de nombres aléatoires mais de nombres pseudo aléatoires. Utilisez le code suivant
Par exemple:
Vous devez appeler
sinon les nombres ne seront pas presque aléatoires.
la source
Je viens de trouver ça sur Internet. Cela devrait fonctionner:
la source