Stworzyłem klasę QuickRandom
, której zadaniem jest szybkie tworzenie liczb losowych. To naprawdę proste: po prostu weź starą wartość, pomnóż przez a double
i weź część dziesiętną.
Oto moja QuickRandom
klasa w całości:
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;
}
}
A oto kod, który napisałem, aby go przetestować:
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);
}
Jest to bardzo prosty algorytm, który po prostu mnoży poprzednią wartość podwójną przez podwójną „magiczną liczbę”. Złożyłem to dość szybko, więc prawdopodobnie mógłbym to ulepszyć, ale dziwne, wydaje się, że działa dobrze.
Oto przykładowe dane wyjściowe zakomentowanych wierszy w main
metodzie:
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. Całkiem losowo. W rzeczywistości działałoby to w przypadku generatora liczb losowych w grze.
Oto przykładowe dane wyjściowe części nieskomentowanej:
5456313909
1427223941
Łał! Działa prawie 4 razy szybciej niż Math.random
.
Pamiętam, że czytałem gdzieś, że Math.random
używano System.nanoTime()
i mnóstwo szalonych rzeczy dotyczących modułu i podziału. Czy to naprawdę konieczne? Mój algorytm działa znacznie szybciej i wydaje się dość przypadkowy.
Mam dwa pytania:
- Czy mój algorytm „wystarczająco dobre” (o, powiedzmy, na stadionie, gdzie naprawdę liczb losowych nie są zbyt ważne)?
- Dlaczego robi
Math.random
tak dużo, kiedy wydaje się, że wystarczy zwykłe pomnożenie i wycięcie ułamka dziesiętnego?
new QuickRandom(0,5)
lub new QuickRandom(.5, 2)
. Oba będą wielokrotnie wyświetlać 0 dla twojego numeru.