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 1000niepowtarzalne 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 Mathklasa 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 0do 1. Sam numer 1 nie jest zawarty w zakresie.

Przykład:

Kod Wyjście konsoli
public class Main
{
   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       System.out.println(Math.random());
     }
   }
}
0.9703753971734451
0.09979423801773157
0.994048474709053
0.2852203204171295
0.13551248551226025
0.3128547131272822
0.5342480554101412
0.6817369932044817
0.1840767788961758
0.06969563435451254

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
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6);
   }

   public static void main(String[] args)
   {
      for (int i = 0; i < 10; i++)
      {
         int x = getRandomDieNumber();
         System.out.println(x);
      }
   }
}
5
2
3
3
2
4
1
1
5
0

Funkcja getRandomDieNumber()zwraca losową liczbę całkowitą z zakresu 0..5włą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
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6) + 1;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       int x = getRandomDieNumber();
       System.out.println(x);
     }
   }
}
3
2
1
3
6
5
6
1
6
6

Teraz jest idealnie!



3. Randomklasa

Java ma specjalną Randomklasę, 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 Randomobiekcie.

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.0samej liczby.

Random r = new Random();
float f = r.nextFloat();

int nextInt(int max)

Ta metoda zwraca losową liczbę całkowitą z zakresu [0, max). 0mieści się w zakresie, ale maxnim 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 billiondo +2 billion.

A dokładniej od -2147483648do +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 longs.

boolean nextBoolean()

Ta metoda zwraca losową booleanwartość: falselub 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.

Losowa klasa

W naszym przypadku szczyt rozkładu wartości będzie o godz0.5