1. Pseudorandomtall

Noen ganger står en programmerer overfor tilsynelatende enkle oppgaver: "velg en tilfeldig film fra en bestemt liste", "velg en lotterivinner", "bland spillelisten når brukeren rister smarttelefonen sin", "velg et tilfeldig nummer for å kryptere en melding" , etc. I hvert tilfelle stiller utvikleren et logisk spørsmål: hvordan får man et tilfeldig tall?

Det er faktisk ganske vanskelig å få et virkelig tilfeldig tall. Faktisk er det så vanskelig at spesielle matematiske koprosessorer bygges inn i noen datamaskiner for å generere tall som tilfredsstiller alle kravene til ekte tilfeldighet.

Programmerere kom opp med sin egen løsning: pseudotilfeldige tall . Pseudorandom-tall er en slags sekvens, hvis tall ser ut til å være tilfeldige. Men ved å utføre en nøye analyse, kan en ekspert finne visse mønstre i sekvensen. Slike tall er ikke egnet for å kryptere hemmelige dokumenter, men de er nok til å simulere terningkast i et spill.

Det er mange algoritmer for å generere en sekvens av pseudotilfeldige tall. Nesten alle genererer det neste tilfeldige tallet basert på det forrige tallet og noen ekstra hjelpetall.

For eksempel vil dette programmet vise 1000ikke-repeterende tall:

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());
     }
   }
}

Vi snakker forresten ikke om pseudorandomtall her. Vi snakker om en sekvens av pseudorandom-tall. Ser man på et enkelt tall, er det umulig å si om det er tilfeldig eller ikke.

Det er faktisk forskjellige måter å få et tilfeldig tall på:

public static int getRandomNumber()
{
   return 4; // Here's a random number (we got it by rolling a die)
}

2.Math.random()

I Java Mathhar klassen en spesiell metode som returnerer et tilfeldig tall. Og som du kanskje gjetter, heter metoden random. Generelt, her er hvordan det ser ut å kalle denne metoden:

Math.random()

Denne metoden tar ingen parametere og returnerer et pseudorandom reelt tall i området fra 0til 1. Selve tallet 1 er ikke inkludert i utvalget.

Eksempel:

Kode Konsollutgang
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

Men hva om denne metoden ikke er helt det du trenger? Anta at du vil skrive et program som simulerer å kaste en sekssidig terning. Hvordan får du tilfeldige heltall i området 1..6, i stedet for reelle tall i området 0..1?

Det er faktisk ganske enkelt.

Først må du kartlegge området [0, 1)til [0, 6). For å gjøre dette, multipliser ganske enkelt resultatet returnert med random()med 6. For å få heltall må du selvfølgelig runde opp:

Kode Konsollutgang
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

Returnerer getRandomDieNumber()et tilfeldig heltall i området 0..5inklusive. Men det vil ikke være et tall i settet 1, 2, 3, 4, 5, 6. Det vil være et nummer i settet 0, 1, 2, 3, 4, 5.

Hvis det du trenger er tall i settet 1, 2, 3, 4, 5, 6, legger du bare til ett til de tilfeldige tallene:

Kode Konsollutgang
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

Nå er det perfekt!



3. Randomklasse

Java har en spesiell Randomklasse som innkapsler en sekvens av pseudotilfeldige tall. Du kan lage flere objekter i Randomklassen. Hvert av disse objektene vil generere sin egen sekvens av pseudotilfeldige tall.

Dette er en superinteressant klasse med mange interessante metoder. La oss starte med det enkleste.

double nextDouble()

Denne metoden returnerer et tilfeldig reelt tall i området 0.0- 1.0. Den er veldig lik metoden Math.random(). Og ikke rart, siden Math.random()metoden ganske enkelt kaller nextDouble()metoden på et Randomobjekt.

float nextFloat()

Denne metoden er veldig lik metoden nextDouble(), men det returnerte tilfeldige tallet er en float. Den ligger også i området 0.0- 1.0. Og, som alltid i Java, inkluderer ikke rekkevidden 1.0selve nummeret.

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

int nextInt(int max)

Denne metoden returnerer et tilfeldig heltall i området [0, max). 0er inkludert i sortimentet, men maxer det ikke.

Med andre ord, hvis du ønsker å få et tilfeldig tall i settet 1, 2, 3, 4, 5, 6, må du legge til ett til det returnerte tilfeldige tallet:

Random r = new Random();
int x = r.nextInt(6) + 1;

int nextInt()

Denne metoden ligner den forrige, men den tar ingen parametere. Så hva er området for returverdiene? Fra -2 billiontil +2 billion.

Vel, for å være presis, fra -2147483648til +2147483647.

long nextLong()

Denne metoden ligner på nextInt()metoden, men returverdien vil falle et sted i hele det mulige området på longs.

boolean nextBoolean()

Denne metoden returnerer en tilfeldig booleanverdi: falseeller true. Dette er veldig praktisk når du trenger å få en lang sekvens med tilfeldige boolske verdier.

void nextBytes(byte[] data)

Denne metoden returnerer ingenting (siden returtypen er void). I stedet fyller den den beståtte matrisen med tilfeldige verdier. Dette er veldig nyttig når du trenger en stor buffer fylt med tilfeldige data.

double nextGaussian()

Denne metoden returnerer et tilfeldig reelt tall i området 0.0- 1.0. Tallene er imidlertid ikke jevnt fordelt i dette området. I stedet følger de en normalfordeling .

Verdier nær midten av området ( 0.5) vil forekomme oftere enn verdier i enden av området.

Tilfeldig klasse

I vårt tilfelle vil toppen av verdifordelingen være på0.5