Jestem trochę zmieszany, jak to zrobić. Wiem, że mogę używać losowej klasy do generowania liczb losowych, ale nie wiem jak określić i wygenerować 8-bajtową liczbę?Generowanie 8-bajtowego numeru w Javie
dzięki, Vuk
Jestem trochę zmieszany, jak to zrobić. Wiem, że mogę używać losowej klasy do generowania liczb losowych, ale nie wiem jak określić i wygenerować 8-bajtową liczbę?Generowanie 8-bajtowego numeru w Javie
dzięki, Vuk
Należy pamiętać, że klasa java.util.Random
wykorzystuje ziarno 48-bitowe, więc nie wszystkie wartości 8-bajtowych (sekwencje 64 bitów) mogą być generowane przy użyciu tej klasy . Z powodu tego ograniczenia sugeruję użycie SecureRandom
i nextBytes
method w tej sytuacji.
Użycie jest podobne do rozwiązania java.util.Random
.
SecureRandom sr = new SecureRandom();
byte[] rndBytes = new byte[8];
sr.nextBytes(rndBytes);
tutaj Dlatego ziarno 48-bitowe nie wystarcza:
Random
realizuje pseudo losowy generator, który oznacza, że jest deterministyczny.Random
określa przyszłą sekwencję bitów.Random
.podstawie @Peter Lawreys excellent answer (to zasługuje na upvotes!) Oto rozwiązanie tworzenia java.util.Random
z 2 × 48-bitowy nasion. To znaczy, instancja java.util.Random
zdolna do generowania wszystkich możliwych long
s.
class Random96 extends Random {
int count = 0;
ExposedRandom extra48bits;
class ExposedRandom extends Random {
public int next(int bits) { // Expose the next-method.
return super.next(bits);
}
}
@Override
protected int next(int bits) {
if (count++ == 0)
extra48bits = new ExposedRandom();
return super.next(bits)^extra48bits.next(bits) << 1;
}
}
Może to być wykonane albo z tablicy bajtów długości 8:
byte[] byteArray = new byte[8];
random.nextBytes(byteArray);
lub zmiennej typu long
(co oznacza liczby 8-bajtowych)
long randomLong = random.nextLong();
Należy zauważyć, że żadna z tych dwóch metod nie jest w stanie wygenerować wszystkich możliwe wartości 8 bajtów. Zobacz moją odpowiedź. – aioobe
@aioobe: możesz wyjaśnić, dlaczego? Czytałem dokumenty i przeczytałem implementację i nadal nie mam jasnego zrozumienia. Jest dość złożony (oparty na matematyce) algorytm i jak rozumiem, generuje wartości zależne. A jeśli to prawda, to jedna przypadkowa instancja nie generuje wszystkich możliwych wartości długich. Ale różne "losowe" (z różnymi "punktami początkowymi") mają. Czy mam rację? – Roman
Zaktualizowałem moją odpowiedź. – aioobe
Trochę regulacji z kodem here:
import java.util.Random;
/** Generate 10 random integers in the range 0..99. */
public final class RandomByte {
public static final void main(String... aArgs){
log("Generating 10 random integers in range 0..255.");
//note a single Random object is reused here
Random randomGenerator = new Random();
for (int idx = 1; idx <= 10; ++idx){
int randomInt = randomGenerator.nextInt(256);
// int randomInt = randomGenerator.nextBytes(256);
log("Generated : " + randomInt);
}
log("Done.");
}
private static void log(String aMessage){
System.out.println(aMessage);
}
}
Niektóre dalsze czytanie: Math.random() versus Random.nextInt(int)
Należy zauważyć, że klasa 'Random' nie jest w stanie wygenerować wszystkich możliwych 8-bajtowych wartości. – aioobe
Typ long
jest 8 bajtów podpisane całkowitą, więc Random.nextLong()
wydaje się robić to, co chcesz. Lub jeśli trzeba tablicę bajtów w wyniku:
byte[] result = new byte[8];
Random.nextBytes(result);
Należy zauważyć, że klasa 'Random' nie jest w stanie wygenerować wszystkich możliwych longów. – aioobe
Zgadzam się z punktem @aioobe o losowym użyciu 48-bitowego materiału siewnego. SecureRandom to lepsze rozwiązanie. Jednak aby odpowiedzieć na pytania OP, w jaki sposób korzystać z klasy Losowe i nadal pozwalać na wszystkie możliwe 8-bajtowe wartości, należy okresowo resetować nasiona.
int counter = 0;
Random rand = new Random();
Random rand2 = new Random();
if (++counter == 0) rand = new Random(); // reset every 4 billion values.
long randomLong = rand.nextLong()^rand2.nextLong() << 1;
Tylko losowo pozwala na sekwencję 2^47 długich wartości. Używając dwóch generatorów losowych, które ciągle przeskakują w sekwencji, otrzymujesz dwie 2^47 * 2^47 możliwych wartości. Użycie funkcji < < 1 polega na uniknięciu wpływu, jaki ma posiadanie obu wysięgników na to samo nasienie (w tym przypadku^powodowałoby 0 dla 4 miliardów wartości z rzędu).
+1, Świetna odpowiedź. Interesujące notatki dotyczące resetowania i przesunięcia w lewo! Chciałbym, aby odpowiedź była jeszcze lepsza, jeśli obudowałeś przypadek losowy w annonymous subclass of Random. – aioobe
Czy dwa obiekty losowe nie utworzą identycznych liczb losowych, ponieważ oba te elementy będą miały to samo ziarno? (na szybkim komputerze System.currentTimeMillis() będzie taki sam dla obu?) –
W starych wersjach Javy jest to prawda. Z wersji Java 5.0 Random używa System.nanoTime() i licznika AtomicLong. –
nie jest fajnie zostawić ten sam komentarz pod każdą odpowiedzią. – Roman
Dlaczego nie? Myślę, że to w porządku. Dotyczy to każdej odpowiedzi, którą skomentowałem. – aioobe
Moje intuicyjne rozwiązanie polegałoby na wygenerowaniu dwóch wartości 4-bajtowych. Jeśli rozumiem cię poprawnie, to nie zadziałałoby, ponieważ dwie wartości byłyby wykluczone (lub przynajmniej mało prawdopodobne) z równości przy dwukrotnym użyciu tego samego Generatora. Na przykład. FF FF nie byłby tak prawdopodobny jak FF AA? Nie wiem, w jaki sposób realizowane są PRG, więc zaskoczyło mnie to, ponieważ oczekiwałbym, że każda liczba będzie (pseudo-) niezależna od poprzednich liczb. – zockman