Générez des nombres aléatoires uniformément sur toute une plage

93

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?

anand
la source
2
Construisez un Dice-O-Matic: gamesbyemail.com/News/DiceOMatic
Jarett Millard
1
Je n'avais aucune idée que le C ++ rand()était uniforme. Quelle bibliothèque utilisez-vous? cstdlib.h's rand()n'est PAS uniforme: cplusplus.com/reference/cstdlib/rand
Mike Warren
3
Non, rand () est uniforme (sauf dans certaines premières implémentations de bogues). ce qui n'est pas uniforme, c'est l'utilisation de l'opérateur module '%' pour restreindre la plage. Voir stackoverflow.com/questions/2999075/… pour une solution appropriée, ou si vous avez 'arc4random_uniform' disponible, vous pouvez également l'utiliser directement.
John Meacham
@ Alien01: Envisageriez-vous de changer la réponse acceptée par celle de "Chaussure" ("Pourquoi rand est une mauvaise idée" etc.)? Ma réponse est vraiment dépassée et chaque fois que j'obtiens un vote positif, j'ai l'impression que quelqu'un court dans la mauvaise allée.
peterchen
Beau livre blanc sur le hasard en c ++ 11.
Pupsik

Réponses:

153

Pourquoi randune mauvaise idée

La plupart des réponses que vous avez obtenues ici utilisent la randfonction 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 de RAND_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:

const int range_from  = 0;
const int range_to    = 10;
std::random_device                  rand_dev;
std::mt19937                        generator(rand_dev());
std::uniform_int_distribution<int>  distr(range_from, range_to);

std::cout << distr(generator) << '\n';

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:

std::vector<int> vec = {4, 8, 15, 16, 23, 42};

std::random_device random_dev;
std::mt19937       generator(random_dev());

std::shuffle(vec.begin(), vec.end(), generator);

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.

Chaussure
la source
22
ATTENTION à cette réponse, car elle est beaucoup plus moderne.
gsamaras
C'est la bonne réponse. Merci! Pourtant, j'aimerais voir une description plus détaillée de chaque étape de ce code. Par exemple, qu'est-ce qu'un mt19937type?
Apollo
@Apollo La documentation dit "Mersenne Twister 32 bits de Matsumoto et Nishimura, 1998". Je suppose que c'est un algorithme pour générer des nombres pseudo-aléatoires.
Chaussure du
@Shoe, pour une plage donnée, il génère un nombre de même ordre, 1 9 6 2 8 7 1 4 7 7. Savez-vous comment randomiser cela chaque fois que nous exécutons le programme?
1
@Richard Quelle est l'alternative?
Chaussure du
59

[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:

((double) rand() / (RAND_MAX+1)) * (max-min+1) + min

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.

Peterchen
la source
4
BigRand peut donner de meilleurs résultats même lorsque la plage souhaitée ne dépasse pas RAND_MAX. Considérez quand RAND_MAX est 32767 et que vous voulez 32767 valeurs possibles - deux de ces 32768 nombres aléatoires (y compris zéro) vont être mappés vers la même sortie et auront deux fois plus de chances de se produire que les autres. À peine une propriété aléatoire idéale!
Mark Ransom
7
(RAND_MAX + 1) est une mauvaise idée. Cela peut reculer et vous donner une valeur négative. Mieux vaut faire quelque chose comme: ((double) RAND_MAX) + 1.0
Demi
3
@peterchen: Je pense que vous avez mal compris ce que disait demi. Elle voulait dire ceci: ( rand() / ((double)RAND_MAX+1)) * (max-min+1) + min déplacer simplement la conversion pour doubler et éviter le problème.
Mooing Duck
3
En outre, cela change simplement la distribution des 32767 valeurs inférieures de la plage à 32767 valeurs uniformément réparties dans la plage, et les 4017233 valeurs restantes ne seront jamais sélectionnées par cet algorithme.
Mooing Duck
1
La réponse donnée est décalée de 1. L'équation correcte est: ((double) rand () / (RAND_MAX + 1.0)) * (max-min) + min Le "max-min + 1" est utilisé lors de l'utilisation de% not * . Vous verrez pourquoi lorsque vous faites min = 0, max = 1. Peterchen ou @ peter-mortensen pourraient-ils le modifier.
davepc
17

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 randutilsbibliothè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é

#include <iostream>
#include "randutils.hpp"
int main() {
    randutils::mt19937_rng rng;
    std::cout << rng.uniform(1,6) << "\n";
}

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++11les <random>, avec qui partage une grande partie de l'interface. Tout en étant théoriquement une dépendance externe, elle Boosta désormais le statut de bibliothèque «quasi-standard», et son Randommodule 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 à la C++11solution:

  • il est plus portable, nécessitant juste le support du compilateur pour C ++ 03
  • il random_deviceutilise 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_devicen'est pas uniquement en-tête, il faut compiler et lier boost_random.

Échantillon minimal: un jet de dé

#include <iostream>
#include <boost/random.hpp>
#include <boost/nondet_random.hpp>

int main() {
    boost::random::random_device                  rand_dev;
    boost::random::mt19937                        generator(rand_dev());
    boost::random::uniform_int_distribution<>     distr(1, 6);

    std::cout << distr(generator) << '\n';
}

Bien que l'échantillon minimal fasse bien son travail, les vrais programmes devraient utiliser une paire d'améliorations:

  • faire mt19937un thread_local: le générateur est assez dodu (> 2 Ko) et vaut mieux ne pas être alloué sur la pile
  • graine mt19937avec plus d'un entier: le Mersenne Twister a un grand état et peut bénéficier de plus d'entropie lors de l'initialisation

Quelques 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 les entropy()retours 0) et, à partir de 2015, MinGW (pas le compilateur le plus utilisé, mais pas un choix ésotérique) imprimera toujours 4sur l'échantillon minimal.

Échantillon minimal: un jet de dé

#include <iostream>
#include <random>
int main() {
    std::random_device                  rand_dev;
    std::mt19937                        generator(rand_dev());
    std::uniform_int_distribution<int>  distr(1, 6);

    std::cout << distr(generator) << '\n';
}

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é

#include <iostream>
#include <random>

int main() {
    std::cout << std::randint(1,6);
}

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 randintfonction 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é

#include <cstdlib>
#include <ctime>
#include <iostream>

int main() {
    std::srand(std::time(nullptr));
    std::cout << (std::rand() % 6 + 1);
}

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é

#include <iostream>

int main() {
    std::cout << 9;   // http://dilbert.com/strip/2001-10-25
}

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.

Alberto M
la source
La randutilsbibliothèque s'appelle maintenant PCG.
tay10r le
11

Si RAND_MAXest 32767, vous pouvez facilement doubler le nombre de bits.

int BigRand()
{
    assert(INT_MAX/(RAND_MAX+1) > RAND_MAX);
    return rand() * (RAND_MAX+1) + rand();
}
Mark Ransom
la source
Je ne pense pas que cela fonctionne. Les générateurs de nombres pseudo aléatoires sont généralement déterministes. Par exemple, si le premier randappel revient 0x1234et le second 0x5678, alors vous obtenez 0x12345678. C'est le seul numéro que vous pouvez obtenir qui commence par 0x1234, car le numéro suivant le sera toujours 0x5678. Vous obtenez des résultats 32 bits, mais vous n'avez que 32768 numéros possibles.
user694733
@ user694733 un bon générateur de nombres aléatoires a une période supérieure au nombre de sorties qu'il peut générer, donc 0x1234 ne sera pas toujours suivi de 0x5678.
Mark Ransom
9

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.

Jeff Thomas
la source
J'ai travaillé sur uniform_int avec un merseinne twister et malheureusement pour certaines plages, les valeurs renvoyées par uniform_int ne sont pas aussi uniformes que je m'y attendais. Par exemple, uniform_int <> (0, 3) a tendance à produire plus de 0 que de 1 ou de 2
ScaryAardvark
@ScaryAardvark qui ressemble à une mauvaise implémentation de l' 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.
Mark Ransom
@ Mark Ransom. Oui, je suis entièrement d'accord.
ScaryAardvark
8

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.

Caisse à savon
la source
Je ne peux utiliser aucune bibliothèque tierce? Je suis limité au C ++ uniquement.
anand
Ensuite, prenez la voie virile, implémentez AES ou un autre algorithme de cryptage.
SoapBox
2
RC4 est simple à coder et suffisamment aléatoire pour tous les besoins pratiques (sauf WEP, mais ce n'est pas entièrement la faute de RC4). Je le pense, c'est un code incroyablement trivial. Comme, 20 lignes environ. L'entrée Wikipedia a un pseudo-code.
Steve Jessop
4
Pourquoi ne pouvez-vous pas utiliser de code tiers? S'il s'agit d'une question de devoir, vous devriez le dire, car beaucoup de gens préfèrent donner des conseils utiles au lieu de fournir des solutions complètes dans ce cas. Si ce n'est pas un devoir, allez botter le gars qui dit "pas de code tiers", parce que c'est un crétin.
DevSolar
Lien plus direct vers la documentation de la fonction OpenSSL rand (): openssl.org/docs/crypto/rand.html#
DevSolar
5

Vous devriez rechercher RAND_MAXvotre compilateur / environnement particulier. Je pense que vous verriez ces résultats si vous rand()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_MAXet un peu plus de détails sur votre environnement.

Abelenky
la source
3

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 () .

Rob Walker
la source
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?
anand
2

Ce n'est pas le code, mais cette logique peut vous aider.

static double rnd(void)
{
   return (1.0 / (RAND_MAX + 1.0) * ((double)(rand())) );
}

static void InitBetterRnd(unsigned int seed)
{
    register int i;
    srand( seed );
    for( i = 0; i < POOLSIZE; i++){
        pool[i] = rnd();
    }
}

 // This function returns a number between 0 and 1
 static double rnd0_1(void)
 {
    static int i = POOLSIZE-1;
    double r;

    i = (int)(POOLSIZE*pool[i]);
    r = pool[i];
    pool[i] = rnd();
    return (r);
}
user3503711
la source
2

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 appeler random().

Jason Coco
la source
1

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.

uint32_t rand_range_low(uint32_t low, uint32_t high)
{
    uint32_t val;
    // only for 0 < range <= RAND_MAX
    assert(low < high);
    assert(high - low <= RAND_MAX);

    uint32_t range = high-low;
    uint32_t scale = RAND_MAX/range;
    do {
        val = rand();
    } while (val >= scale * range); // since scale is truncated, pick a new val until it's lower than scale*range
    return val/scale + low;
}

et pour les valeurs supérieures à RAND_MAX, vous voulez quelque chose comme

uint32_t rand_range(uint32_t low, uint32_t high)
{
    assert(high>low);
    uint32_t val;
    uint32_t range = high-low;
    if (range < RAND_MAX)
        return rand_range_low(low, high);
    uint32_t scale = range/RAND_MAX;
    do {
        val = rand() + rand_range(0, scale) * RAND_MAX; // scale the initial range in RAND_MAX steps, then add an offset to get a uniform interval
    } while (val >= range);
    return val + low;
}

C'est à peu près comment std :: uniform_int_distribution fait les choses.

benf
la source
0

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.

Kluge
la source
«uniformément distribué» a une signification bien définie, et les générateurs aléatoires standard se rapprochent généralement.
peterchen
Oui, vous avez raison, les générateurs de nombres aléatoires devraient produire une sortie qui, avec le temps, est généralement uniforme dans sa distribution. Je suppose que mon point est que sur un petit nombre d'instances (6 comme indiqué dans l'exemple), la sortie ne sera pas toujours uniforme.
Kluge
Kluge a raison. Une distribution uniforme dans un petit échantillon indique que l'échantillon n'est certainement pas aléatoire.
Bill le lézard
1
Bill, ça n'indique rien de tel. Les petits échantillons n'ont généralement pas de sens, mais si le RNG est censé être uniforme et que la sortie est uniforme, pourquoi est-ce pire qu'un petit échantillon non uniforme?
Dan Dyer
2
Des distributions significatives dans les deux cas indiquent un caractère non aléatoire: je pense que Bill signifie simplement que 6 résultats équidistants seraient également suspects. Dans l'OP, 6 valeurs se situent dans une plage de 32k / 4M, soit <1% de la plage souhaitée. La probabilité qu'il s'agisse d'un faux positif est trop faible pour être discutée.
Steve Jessop
0

La solution donnée par man 3 rand pour un nombre compris entre 1 et 10 inclus est:

j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));

Dans votre cas, ce serait:

j = min + (int) ((max-min+1) * (rand() / (RAND_MAX + 1.0)));

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.

calandoa
la source
1
Cela ne fait que réorganiser la distribution pour qu'elle paraisse plus uniforme, mais ce n'est plus même pour les grandes plages (comme le cas de l'OP)
Mooing Duck
0

@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 ().

Maître rituel
la source
0

Voici la solution que j'ai trouvée:

#include "<stdlib.h>"

int32_t RandomRange(int32_t min, int32_t max) {
    return (rand() * (max - min + 1) / (RAND_MAX + 1)) + min;
}

Il s'agit d'une solution de compartiment, conceptuellement similaire aux solutions utilisées rand() / RAND_MAXpour 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 fichier int32_t. Si des RAND_MAXcalculs 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 (comme int64_t) pour le calcul. Deuxièmement, si int64_test utilisé mais RAND_MAXest toujours 32767, à des plages plus grandes que RAND_MAXvous 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.

Ryan
la source
-1

Bien sûr, le code suivant ne vous donnera pas de nombres aléatoires mais de nombres pseudo aléatoires. Utilisez le code suivant

#define QUICK_RAND(m,n) m + ( std::rand() % ( (n) - (m) + 1 ) )

Par exemple:

int myRand = QUICK_RAND(10, 20);

Vous devez appeler

srand(time(0));  // Initialize random number generator.

sinon les nombres ne seront pas presque aléatoires.

Michael Haephrati
la source
1
La question demande une répartition uniforme. Cette solution proposée ne produira pas une distribution uniforme. La bibliothèque C ++ standard a des fonctionnalités pour la génération de nombres pseudo-aléatoires . Ceux -ci fournissent une distribution uniforme, sur demande.
IInspectable
-3

Je viens de trouver ça sur Internet. Cela devrait fonctionner:

DWORD random = ((min) + rand()/(RAND_MAX + 1.0) * ((max) - (min) + 1));
anand
la source
Veuillez préciser ce dont vous avez besoin, il existe des tonnes d'algorithmes pour PRNG. En outre, ce serait plus facile si vous modifiez votre question principale au lieu de publier des réponses.
peterchen
Cela fonctionne mieux pour moi ... Je suis capable d'obtenir des nombres aléatoires mieux distribués avec cette formule ..
anand
4
Si votre plage dépasse RAND_MAX, les résultats peuvent ne pas être uniformes. Autrement dit, il y a des valeurs dans la plage qui ne seront pas représentées quel que soit le nombre de fois où vous appelez votre fonction.
dmckee --- ancien chaton modérateur
4
De plus, si max et min sont tous les deux des int non signés, et min est 0, et max est MAX_UINT, alors ((max) - (min) +1) sera 0, et le résultat sera toujours 0. Attention aux débordements en faisant ce type de calcul! Comme indiqué par dmckee, cela étend la distribution sur la plage de destination, mais ne garantit pas plus de valeurs uniques RAND_MAX.
jesup