Hice una clase llamada QuickRandom
, y su trabajo es producir números aleatorios rápidamente. Es realmente simple: solo toma el valor anterior, multiplica por a double
y toma la parte decimal.
Aquí está mi QuickRandom
clase en su totalidad:
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;
}
}
Y aquí está el código que escribí para probarlo:
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);
}
Es un algoritmo muy simple que simplemente multiplica el doble anterior por un "número mágico" doble. Lo uní bastante rápido, por lo que probablemente podría mejorarlo, pero extrañamente, parece estar funcionando bien.
Esta es una salida de muestra de las líneas comentadas en el main
método:
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. Bastante al azar. De hecho, eso funcionaría para un generador de números aleatorios en un juego.
Aquí está la salida de muestra de la parte no comentada:
5456313909
1427223941
¡Guauu! Se realiza casi 4 veces más rápido que Math.random
.
Recuerdo haber leído en algún lugar que Math.random
usaba System.nanoTime()
toneladas de módulo loco y cosas de división. ¿Es eso realmente necesario? Mi algoritmo funciona mucho más rápido y parece bastante aleatorio.
Tengo dos preguntas:
- ¿Es mi algoritmo "suficientemente bueno" (para, por ejemplo, un juego, donde los números realmente aleatorios no son demasiado importantes)?
- ¿Por qué hace
Math.random
tanto cuando parece simple multiplicación y cortar el decimal será suficiente?
new QuickRandom(0,5)
o new QuickRandom(.5, 2)
. Ambos emitirán repetidamente 0 para su número.