Eu fiz uma aula chamada QuickRandom
, e seu trabalho é produzir números aleatórios rapidamente. É realmente simples: basta pegar o valor antigo, multiplicar por a double
e pegar a parte decimal.
Aqui está minha QuickRandom
turma na íntegra:
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;
}
}
E aqui está o código que escrevi para testá-lo:
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);
}
É um algoritmo muito simples que simplesmente multiplica o dobro anterior por um "número mágico" duplo. Eu juntei tudo rapidamente, então provavelmente poderia melhorar, mas estranhamente, parece estar funcionando bem.
Esta é uma saída de amostra das linhas comentadas no 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
Hum. Bastante aleatório. De fato, isso funcionaria para um gerador de números aleatórios em um jogo.
Aqui está um exemplo de saída da parte não comentada:
5456313909
1427223941
Uau! Ele executa quase 4 vezes mais rápido que Math.random
.
Lembro-me de ler em algum lugar que Math.random
usava System.nanoTime()
e toneladas de módulos malucos e coisas de divisão. Isso é mesmo necessário? Meu algoritmo executa muito mais rápido e parece bastante aleatório.
Eu tenho duas perguntas:
- Meu algoritmo é "bom o suficiente" (para, digamos, um jogo, onde números realmente aleatórios não são muito importantes)?
- Por que
Math.random
fazer tanto quando parece simples multiplicação e cortar o decimal é suficiente?
new QuickRandom(0,5)
ou new QuickRandom(.5, 2)
. Ambos produzirão repetidamente 0 para o seu número.