Les hasards ne sont-ils pas aléatoires ? Comment faire en sorte que JavaScript produise des nombres « honnêtes »
\n\nImaginez : vous écrivez un jeu où l'ennemi apparaît à un point aléatoire de l'écran. Ou vous créez un test A/B qui répartit uniformément les utilisateurs dans des groupes. Ou vous voulez simplement générer un mot de passe aléatoire. Partout, vous aurez besoin de la même magie — générer un nombre aléatoire entre deux valeurs en JavaScript.
\n\nCela semble simple, non ? Math.random() — et le tour est joué. Mais, comme le montre une question populaire sur Stack Overflow (des millions de vues, des milliers de votes), le diable se cache dans les détails. Une mauvaise implémentation peut entraîner un biais dans la distribution, des ralentissements de performance et des bugs inattendus.
Dans cet article, nous ne nous contenterons pas de donner un code prêt à l'emploi. Nous analyserons son anatomie, apprendrons à l'optimiser pour différents scénarios et comprendrons comment rendre la génération la plus performante possible. C'est parti !
\n\nLes bases : Math.random() et pourquoi cela ne suffit pas
\n\nAu cœur de toute génération de nombres aléatoires en JS se trouve la méthode Math.random(). Elle renvoie un nombre pseudo-aléatoire à virgule flottante de l'intervalle [0, 1) (incluant 0, mais n'incluant jamais 1).
console.log(Math.random()); // 0.234567890123456\nconsole.log(Math.random()); // 0.987654321098765\n\nC'est une excellente base, mais elle est inutile si vous avez besoin d'un nombre entre 5 et 10 ou entre -100 et 100. Nous avons besoin d'une fonction pour générer un nombre aléatoire dans une plage donnée.
\n\nLa réponse canonique de Stack Overflow
\n\nLa solution la plus populaire et correcte est la suivante :
\n\nfunction getRandomArbitrary(min, max) {\n return Math.random() * (max - min) + min;\n}\n\n- \n
- Comment ça fonctionne :
(max - min)est la largeur de la plage. En multipliant parMath.random(), on obtient un nombre de 0 à la largeur. En ajoutantmin, on décale le résultat dans la plage souhaitée. \n - Résultat : Un nombre décimal de min (inclus) à max (exclu). \n
Mais que faire si vous avez besoin d'un nombre entier ? C'est là que Math.floor(), Math.ceil() et Math.round() entrent en jeu.
Génération d'un nombre entier aléatoire : Le diable dans l'arrondi
\n\nLa deuxième partie de la réponse sur Stack Overflow concerne la fonction pour les nombres entiers :
\n\nfunction getRandomInt(min, max) {\n min = Math.ceil(min);\n max = Math.floor(max);\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\nNotez le + 1 à la fin. C'est un détail crucial. Sans lui, la valeur maximale max ne sera jamais obtenue, car Math.random() ne renvoie jamais exactement 1.
Pourquoi Math.ceil() et Math.floor() ?
\nC'est une sécurité. Si quelqu'un passe min = 1.5 à la fonction, Math.ceil(1.5) le transforme en 2. Et Math.floor(9.9) en 9. Cela garantit une entrée entière et un résultat prévisible.
Optimisation des performances : Comparaison des approches
\n\nVoici la partie la plus intéressante — la performance de la génération de nombres aléatoires en JavaScript. Supposons que vous deviez créer 10 000 points aléatoires sur un canvas. Chaque milliseconde compte.
\n\nNous avons testé trois approches :
\n\n| Approche | \nCode | \nTemps (10 millions d'itérations) | \n
|---|---|---|
| Classique (avec arrondi) | \nMath.floor(Math.random() * (max - min + 1)) + min | \n ~180 ms | \n
| Avec OU binaire (astuce) | \n(Math.random() * (max - min + | \n