Comment est-il aléatoirement Math.random de JavaScript?

Pendant 6 ans, j'ai eu une page génératrice de nombres aléatoires sur mon site. Pendant longtemps, ce fut le premier ou le deuxième résultat sur Google pour «générateur de nombres aléatoires» et a été utilisé pour décider des dizaines, sinon des centaines de concours et de dessins sur des forums de discussion et des blogs (je sais parce que je vois les référents dans mon Les journaux Web et vont généralement jeter un oeil).

Aujourd'hui, quelqu'un m'a envoyé un courrier électronique pour me dire que ce n'est peut-être pas aussi aléatoire que je le pensais. Elle a essayé de générer des nombres aléatoires très importants (par exemple, entre 1 et 100000000000000000) et a constaté qu'ils étaient presque toujours le même nombre de chiffres. En effet, j'ai enveloppé la fonction en boucle afin que je puisse générer des milliers de nombres et, bien sûr, pour de très gros nombres, la variation n'était que d'environ 2 ordres de grandeur.

Pourquoi?

Voici la version en boucle, afin que vous puissiez l'essayer par vous-même:

Http://andrew.hedges.name/experiments/random/randomness.html

Il comprend à la fois une mise en œuvre directe tirée du Mozilla Developer Network et un code de 1997 que j'ai glissé sur une page Web qui n'existe plus (Paul Haute "Central Randomizer 1.3"). Voir la source pour voir comment chaque méthode fonctionne.

J'ai lu ici et ailleurs sur Mersenne Twister. Ce qui m'intéresse, c'est pourquoi il n'y aurait pas de variation plus grande dans les résultats de la fonction Math.random intégrée de JavaScript . Merci!

Dit des nombres entre 1 et 100.

  • 9 ont 1 chiffre (1-9)
  • 90 ont 2 chiffres (10-99)
  • 1 a 3 chiffres (100)

Dit des nombres entre 1 et 1000.

  • 9 ont 1 chiffre
  • 90 ont 2 chiffres
  • 900 ont 3 chiffres
  • 1 a 4 chiffres

etc.

Donc, si vous sélectionnez certains au hasard, alors la grande majorité des nombres sélectionnés auront le même nombre de chiffres, car la grande majorité des valeurs possibles ont le même nombre de chiffres.

Vos résultats sont réellement attendus. Si les nombres aléatoires sont uniformément répartis dans une plage de 1 à 10 ^ n, vous attendez environ 9/10 des nombres pour avoir n chiffres, et 9/100 supplémentaires pour avoir n-1 chiffres.

Il existe différents types de hasard. Math.random vous donne une répartition uniforme des nombres.

Si vous voulez des ordres de grandeur différents, je suggérerais d'utiliser une fonction exponentielle pour créer ce qu'on appelle une distribution de la loi de puissance :

number = Math.floor(Math.exp(Math.random()*Math.log(maxmimum-minimum+1)))+minimum 

Cette ligne devrait vous donner approximativement le même nombre de nombres à 1 chiffre que les chiffres à 2 chiffres et à 3 chiffres.

Il existe également d'autres distributions pour des nombres aléatoires comme la distribution normale (également appelée distribution gaussienne).

Le document suivant explique comment math.random () dans les principaux navigateurs Web est (non) sécurisé: "Suivi temporaire des utilisateurs dans les principaux navigateurs et les fuites et attaques d'informations entre domaines" par Amid Klein (2008) . Ce n'est pas plus fort que les fonctions PRNG intégrées Java ou Windows typiques.

D'autre part, la mise en œuvre de la SFMT de la période 2 ^ 19937-1 nécessite 2496 octets de l'état interne maintenu pour chaque séquence PRNG. Certaines personnes peuvent considérer cela comme un coût impardonnable.

On me paraît parfaitement aléatoire! (Indice: c'est dépendante du navigateur).

Personnellement, je pense que ma mise en œuvre serait meilleure, bien que je l'ai volé de XKCD , qui devrait TOUJOURS être reconnu:

 random = 4; // Chosen by a fair dice throw. Guaranteed to be random. 

Si vous utilisez un numéro comme 10000000000000000000, vous allez au-delà de la précision du type de données que Javascript utilise. Notez que tous les nombres générés se terminent par "00".

J'ai essayé le générateur de nombres pseudorandom JS sur Chaos Game .

Mon triangle Sierpiński dit que c'est assez aléatoire: Fractal

Eh bien, si vous générez des chiffres jusqu'à, disons, 1e6, vous obtiendrez tous les nombres avec une probabilité approximativement égale. Cela signifie également que vous avez seulement une chance sur dix d'obtenir un nombre avec un chiffre de moins. Une chance sur cent d'avoir moins deux chiffres, etc. Je doute que vous verrez beaucoup de différence lors de l'utilisation d'un autre RNG, car vous avez une répartition uniforme sur les nombres, pas leur logarithme.