J'ai créé une classe appelée QuickRandom
, et son travail est de produire rapidement des nombres aléatoires. C'est vraiment simple: il suffit de prendre l'ancienne valeur, de multiplier par a double
et de prendre la partie décimale.
Voici ma QuickRandom
classe 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);
}
C'est un algorithme très simple qui multiplie simplement le double précédent par un double "nombre magique". Je l'ai jeté ensemble assez rapidement, donc je pourrais probablement l'améliorer, mais étrangement, cela semble fonctionner correctement.
Voici un exemple de sortie des lignes commentées dans la 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. Assez aléatoire. En fait, cela fonctionnerait 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
Hou la la! Il fonctionne presque 4 fois plus vite queMath.random
.
Je me souviens avoir lu quelque part qui Math.random
utilisait System.nanoTime()
et des tonnes de modules et de divisions folles. Est-ce vraiment nécessaire? Mon algorithme fonctionne beaucoup plus rapidement et cela semble assez aléatoire.
J'ai deux questions:
- Mon algorithme est-il "assez bon" (pour, par exemple, un jeu, où les nombres vraiment aléatoires ne sont pas trop importants)?
- Pourquoi en
Math.random
faire autant alors qu'il semble qu'une simple multiplication et découper la décimale suffiront?
new QuickRandom(0,5)
ou new QuickRandom(.5, 2)
. Ceux-ci afficheront tous les deux à plusieurs reprises 0 pour votre numéro.