J'ai créé une classe appelée QuickRandom
et son rôle est de produire rapidement des nombres aléatoires. C'est très simple : il suffit de prendre l'ancienne valeur, de la multiplier par une valeur de double
et prendre la partie décimale.
Voici mon QuickRandom
dans son intégralité :
public class QuickRandom {
private double prevNum;
private double magicNumber;
public QuickRandom(double seed1, double seed2) {
if (seed1 >= 1 || seed1 < 0) throw new IllegalArgumentException("Seed 1 must be >= 0 and < 1, not " + seed1);
prevNum = seed1;
if (seed2 <= 1 || seed2 > 10) throw new IllegalArgumentException("Seed 2 must be > 1 and <= 10, not " + seed2);
magicNumber = seed2;
}
public QuickRandom() {
this(Math.random(), Math.random() * 10);
}
public double random() {
return prevNum = (prevNum*magicNumber)%1;
}
}
Et voici le code que j'ai écrit pour le tester :
public static void main(String[] args) {
QuickRandom qr = new QuickRandom();
/*for (int i = 0; i < 20; i ++) {
System.out.println(qr.random());
}*/
//Warm up
for (int i = 0; i < 10000000; i ++) {
Math.random();
qr.random();
System.nanoTime();
}
long oldTime;
oldTime = System.nanoTime();
for (int i = 0; i < 100000000; i ++) {
Math.random();
}
System.out.println(System.nanoTime() - oldTime);
oldTime = System.nanoTime();
for (int i = 0; i < 100000000; i ++) {
qr.random();
}
System.out.println(System.nanoTime() - oldTime);
}
(Wow, je viens de remarquer que le code de test est plus long que celui de la QuickRandom
code. Cela prouve simplement que c'est un algorithme si simple).
Il s'agit d'un algorithme très simple qui multiplie simplement le double précédent par un double "chiffre magique". Je l'ai mis au point assez rapidement, donc je pourrais probablement l'améliorer, mais bizarrement, il semble fonctionner correctement.
Voici un exemple de sortie des lignes commentées dans le fichier main
méthode :
0.612201846732229
0.5823974655091941
0.31062451498865684
0.8324473610354004
0.5907187526770246
0.38650264675748947
0.5243464344127049
0.7812828761272188
0.12417247811074805
0.1322738256858378
0.20614642573072284
0.8797579436677381
0.022122999476108518
0.2017298328387873
0.8394849894162446
0.6548917685640614
0.971667953190428
0.8602096647696964
0.8438709031160894
0.694884972852229
Hm. Plutôt aléatoire. En fait, ça pourrait fonctionner pour un générateur de nombres aléatoires dans un jeu.
Voici un exemple de sortie de la partie non commentée :
5456313909
1427223941
Wow ! Il est presque 4 fois plus rapide que Math.random
.
Je me souviens avoir lu quelque part que Math.random
utilisé System.nanoTime()
et des tonnes de trucs fous de modulation et de division. Est-ce vraiment nécessaire ? Mon algorithme est beaucoup plus rapide et semble assez aléatoire.
J'ai deux questions :
- Mon algorithme est-il "suffisamment bon" (pour, disons, un jeu, où vraiment les nombres aléatoires ne sont pas trop importants) ?
- Pourquoi est-ce que
Math.random
faire autant quand il semble qu'une simple multiplication et la suppression de la décimale suffisent ?