1. Liczby pseudolosowe
Czasami programista staje przed pozornie prostymi zadaniami: „wybierz losowy film z określonej listy”, „wybierz zwycięzcę loterii”, „przetasuj playlistę, gdy użytkownik potrząśnie smartfonem”, „wybierz losową liczbę do zaszyfrowania wiadomości” itp. W każdym przypadku deweloper zadaje logiczne pytanie: jak zdobyć losową liczbę?
W rzeczywistości uzyskanie naprawdę losowej liczby jest raczej trudne. W rzeczywistości jest to tak trudne, że w niektóre komputery wbudowane są specjalne koprocesory matematyczne w celu generowania liczb spełniających wszystkie wymagania prawdziwej losowości.
Programiści wymyślili własne rozwiązanie: liczby pseudolosowe . Liczby pseudolosowe to rodzaj sekwencji, których liczby wydają się być przypadkowe. Jednak przeprowadzając dokładną analizę, ekspert może znaleźć pewne wzorce w sekwencji. Takie liczby nie nadają się do szyfrowania tajnych dokumentów, ale wystarczają do symulacji rzutu kostką w grze.
Istnieje wiele algorytmów generowania sekwencji liczb pseudolosowych. Prawie wszystkie z nich generują następną liczbę losową na podstawie poprzedniej liczby i kilku dodatkowych liczb pomocniczych.
Na przykład ten program wyświetli 1000
niepowtarzalne liczby:
public class Main
{
public static int a = 41;
public static int c = 11119;
public static int m = 11113;
public static int seed = 1;
public static int getNextRandom()
{
seed = (a * seed + c) % m;
return seed;
}
public static void main(String[] args)
{
for (int i = 0; i < 1000; i++)
{
System.out.println(getNextRandom());
}
}
}
Nawiasem mówiąc, nie mówimy tutaj o liczbach pseudolosowych. Mówimy o sekwencji liczb pseudolosowych. Patrząc na pojedynczą liczbę, nie można stwierdzić, czy jest ona przypadkowa, czy nie.
Rzeczywiście, istnieją różne sposoby uzyskania liczby losowej:
public static int getRandomNumber()
{
return 4; // Here's a random number (we got it by rolling a die)
}
2.Math.random()
W Javie Math
klasa ma specjalną metodę, która zwraca liczbę losową. I jak można się domyślić, metoda nazywa się random
. Ogólnie rzecz biorąc, oto jak wygląda wywołanie tej metody:
Math.random()
Ta metoda nie przyjmuje żadnych parametrów i zwraca pseudolosową liczbę rzeczywistą z zakresu od 0
do 1
. Sam numer 1 nie jest zawarty w zakresie.
Przykład:
Kod | Wyjście konsoli |
---|---|
|
|
Ale co, jeśli ta metoda nie jest tym, czego potrzebujesz? Załóżmy, że chcesz napisać program, który symuluje rzut sześcienną kostką. Jak uzyskać losowe liczby całkowite z zakresu 1..6 zamiast liczb rzeczywistych z zakresu 0..1?
Właściwie to całkiem proste.
Najpierw musisz zmapować zakres [0, 1)
na [0, 6)
. Aby to zrobić, po prostu pomnóż zwrócony wynik random()
przez 6
. Oczywiście, aby uzyskać liczby całkowite, musisz zaokrąglić w górę:
Kod | Wyjście konsoli |
---|---|
|
|
Funkcja getRandomDieNumber()
zwraca losową liczbę całkowitą z zakresu 0..5
włącznie. Ale to nie będzie liczba w zbiorze 1, 2, 3, 4, 5, 6
. Będzie to liczba w zestawie 0, 1, 2, 3, 4, 5
.
Jeśli potrzebujesz liczb w zestawie 1, 2, 3, 4, 5, 6
, po prostu dodaj jedną do losowych liczb:
Kod | Wyjście konsoli |
---|---|
|
|
Teraz jest idealnie!
3. Random
klasa
Java ma specjalną Random
klasę, która hermetyzuje sekwencję liczb pseudolosowych. Możesz utworzyć kilka obiektów klasy Random
. Każdy z tych obiektów wygeneruje własną sekwencję liczb pseudolosowych.
To bardzo interesująca klasa z wieloma interesującymi metodami. Zacznijmy od najprostszego.
double nextDouble()
Ta metoda zwraca losową liczbę rzeczywistą z zakresu 0.0
- 1.0
. Jest bardzo podobny do Math.random()
metody. I nic dziwnego, skoro Math.random()
metoda po prostu wywołuje nextDouble()
metodę na Random
obiekcie.
float nextFloat()
Ta metoda jest bardzo podobna do nextDouble()
metody, ale zwrócona liczba losowa to float
. Leży również w przedziale 0.0
- 1.0
. I, jak zawsze w Javie, zakres nie obejmuje 1.0
samej liczby.
Random r = new Random();
float f = r.nextFloat();
int nextInt(int max)
Ta metoda zwraca losową liczbę całkowitą z zakresu [0, max)
. 0
mieści się w zakresie, ale max
nim nie jest.
Innymi słowy, jeśli chcesz otrzymać losową liczbę w zbiorze 1, 2, 3, 4, 5, 6
, musisz dodać jeden do zwróconej liczby losowej:
Random r = new Random();
int x = r.nextInt(6) + 1;
int nextInt()
Ta metoda jest podobna do poprzedniej, ale nie przyjmuje żadnych parametrów. Jaki jest więc zakres jego wartości zwracanych? od -2 billion
do +2 billion
.
A dokładniej od -2147483648
do +2147483647
.
long nextLong()
Ta metoda jest podobna do nextInt()
metody, ale zwracana wartość będzie mieścić się gdzieś w całym możliwym zakresie long
s.
boolean nextBoolean()
Ta metoda zwraca losową boolean
wartość: false
lub true
. Jest to bardzo wygodne, gdy trzeba uzyskać długą sekwencję losowych wartości boolowskich.
void nextBytes(byte[] data)
Ta metoda nic nie zwraca (ponieważ typem zwracanym jest void
). Zamiast tego wypełnia przekazaną tablicę losowymi wartościami. Jest to bardzo przydatne, gdy potrzebny jest duży bufor wypełniony losowymi danymi.
double nextGaussian()
Ta metoda zwraca losową liczbę rzeczywistą z zakresu 0.0
- 1.0
. Jednak liczby nie rozkładają się równomiernie w tym zakresie. Zamiast tego mają rozkład normalny .
Wartości w pobliżu środka zakresu ( 0.5
) będą występować częściej niż wartości na końcach zakresu.
W naszym przypadku szczyt rozkładu wartości będzie o godz0.5