Przejrzałem Rhino source code, aby dowiedzieć się, z której funkcji pseudolosowej korzystają. Najwyraźniej są one fall back dla funkcji Math.random
zdefiniowanej w .
Dokumentacja Math.random
mówi:
Zwraca podwójną wartość ze znakiem dodatnim, większej lub równej 0,0 i mniej niż 1,0. Zwracane wartości są wybierane pseudolosowo z (w przybliżeniu) jednolitym rozkładem z tego zakresu.
Kiedy ta metoda jest pierwszy nazywa, to tworzy jeden nowy generator pseudolosowych-numeryczny, dokładnie tak, jakby przez wyrażenie
new java.util.Random
Ten nowy generator pseudolosowych Numer służy następnie do wszystkich połączeń do tej metody i nie jest używany nigdzie indziej.
Ta metoda jest poprawnie zsynchronizowana, aby umożliwić poprawne użycie przez więcej niż jeden wątek. Jeśli jednak wiele wątków wymaga generowania liczby pseudolosowej z dużą szybkością, może to zmniejszyć rywalizację dla każdego wątku o własny generator liczb pseudolosowych.
Więc sprawdziłem dokumentację java.util.Random
i znalazł this (dla domyślnego konstruktora):
tworzy nowy generator liczb losowych. Jego nasiona są inicjowane wartości w oparciu o aktualny czas:
public Random() { this(System.currentTimeMillis()); }
dwa losowe obiekty utworzone w tym samym milisekundy będzie miał taką samą sekwencję liczb losowych.
Teraz wiemy na pewno, że materiał siewny jest bieżącym czasem w milisekundach. Ponadto, dokumentacja dla second constructor mówi:
Tworzy nowy generator liczb losowych za pomocą jednego długiego materiału siewnego:
public Random(long seed) { setSeed(seed); }
Używane metodą najbliższego utrzymać ten stan liczby pseudolosowy generator.
documentation dla metody setSeed
mówi:
Ustawia nasionko tego generatora liczb losowych za pomocą jednego długiego nasienie. Ogólną umową setSeed jest to, że zmienia stan tego obiektu generatora liczb losowych tak, aby był dokładnie w tym samym stanie, jak gdyby został właśnie utworzony z nasionami argumentów jako nasionami. Metoda setSeed jest realizowany przez klasy Dowolnie w następujący sposób:
synchronized public void setSeed(long seed) {
this.seed = (seed^0x5DEECE66DL) & ((1L << 48) - 1);
haveNextNextGaussian = false;
}
Realizacja setSeed do klasy Dowolnie się stanie wykorzystać tylko 48 bitów danego materiału siewnego. Zasadniczo jednak metoda nadrzędna może wykorzystywać wszystkie 64 bity długiego argumentu jako wartość początkową.Uwaga: Chociaż wartość początkowa to AtomicLong, ta metoda musi być nadal zsynchronizowana, aby zapewnić poprawną semantykę hasNextNextGaussian.
actual method wykorzystywane do generowania liczby losowej jest nextDouble
:
Zwraca obok pseudolosowych równomiernie rozmieszczone podwójną wartość pomiędzy 0,0 i 1,0 z sekwencji tego generatora liczb losowych.
Realizacja funkcji nextDouble
jest następujący:
public double nextDouble() {
return (((long)next(26) << 27) + next(27))
/(double)(1L << 53);
}
Wyraźnie to depends na next
funkcję:
Generuje następny numer pseudolosowego. Podklasa powinna to zmienić, ponieważ jest używana przez wszystkie inne metody.
Realizacja funkcji next
jest następujący:
synchronized protected int next(int bits) {
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (int)(seed >>> (48 - bits));
}
to funkcja pseudolosowych szukasz. Jak to się mówi w dokumentach:
to liniowy przystający generator liczb pseudolosowych, określone przez DH Lehmer i opisane Donald E. Knutha Sztuka programowania, tom 2: Seminumerical algorytmów, rozdział 3.2. 1.
Należy jednak pamiętać, że jest to tylko generator liczb losowych używany przez Rhino. Inne implementacje, takie jak Spidermonkey i V8, mogą mieć własne generatory liczb pseudolosowych.
Cały punkt 'Math.random()' jest taki, że nie można tego przewidzieć (przynajmniej nie bez większych trudności). –
Czy jest ktoś, kto czyta źródło "V8", aby dać nam jednoznaczną odpowiedź? – TiansHUo
@TiansHUo - Przeczytałem kod źródłowy Rhino i odpowiedziałem na pytanie na podstawie tego, co przeczytałem: http://stackoverflow.com/a/13303029/783743 –