1. Pseudoslumptal

Ibland står en programmerare inför till synes enkla uppgifter: "välj en slumpmässig film från en viss lista", "välj en lotterivinnare", "blanda spellistan när användaren skakar sin smartphone", "välj ett slumpmässigt nummer för att kryptera ett meddelande" , etc. I varje fall ställer utvecklaren en logisk fråga: hur får man ett slumptal?

Det är faktiskt ganska svårt att få ett riktigt slumptal. Faktum är att det är så svårt att speciella matematiska samprocessorer är inbyggda i vissa datorer för att generera siffror som uppfyller alla krav på sann slumpmässighet.

Programmerare kom på sin egen lösning: pseudoslumptal . Pseudoslumptal är en slags sekvens, vars nummer verkar vara slumpmässiga. Men genom att utföra en noggrann analys kan en expert hitta vissa mönster i sekvensen. Sådana nummer är inte lämpliga för att kryptera hemliga dokument, men de räcker för att simulera tärningskastet i ett spel.

Det finns många algoritmer för att generera en sekvens av pseudoslumptal. Nästan alla genererar nästa slumptal baserat på föregående nummer och några ytterligare hjälpnummer.

Till exempel kommer detta program att visa 1000icke-upprepade nummer:

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

Förresten, vi pratar inte om pseudoslumptal här. Vi pratar om en sekvens av pseudoslumptal. Om man tittar på ett enda nummer är det omöjligt att avgöra om det är slumpmässigt eller inte.

Det finns faktiskt olika sätt att få ett slumptal:

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 speciell metod som returnerar ett slumptal. Och som du kanske kan gissa heter metoden random. I allmänhet, så här ser det ut att kalla den här metoden:

Math.random()

Denna metod tar inga parametrar och returnerar ett pseudoslumpmässigt reellt tal i intervallet från 0till 1. Själva siffran 1 ingår inte i sortimentet.

Exempel:

Koda Konsolutgång
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 vad händer om den här metoden inte är riktigt vad du behöver? Anta att du vill skriva ett program som simulerar att kasta en sexsidig tärning. Hur får man slumpmässiga heltal i intervallet 1..6, istället för reella tal i intervallet 0..1?

Det är faktiskt ganska enkelt.

Först måste du mappa intervallet [0, 1)till [0, 6). För att göra detta, multiplicera helt enkelt resultatet som returneras med random()med 6. För att få heltal måste du naturligtvis avrunda uppåt:

Koda Konsolutgång
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

Returnerar getRandomDieNumber()ett slumpmässigt heltal i intervallet 0..5inklusive. Men det kommer inte att vara ett nummer i uppsättningen 1, 2, 3, 4, 5, 6. Det blir ett nummer i setet 0, 1, 2, 3, 4, 5.

Om det du behöver är siffror i uppsättningen 1, 2, 3, 4, 5, 6, lägg bara till ett till de slumpmässiga siffrorna:

Koda Konsolutgång
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

Nu är det perfekt!



3. Randomklass

Java har en speciell Randomklass som kapslar in en sekvens av pseudoslumptal. Du kan skapa flera objekt i Randomklassen. Vart och ett av dessa objekt kommer att generera sin egen sekvens av pseudoslumptal.

Det här är en superintressant klass med många intressanta metoder. Låt oss börja med det enklaste.

double nextDouble()

Denna metod returnerar ett slumpmässigt reellt tal i intervallet 0.0- 1.0. Det är väldigt likt metoden Math.random(). Och inte konstigt, eftersom Math.random()metoden helt enkelt anropar nextDouble()metoden på ett Randomobjekt.

float nextFloat()

Denna metod är mycket lik metoden nextDouble(), men det returnerade slumptalet är en float. Den ligger också i sortimentet 0.0- 1.0. Och, som alltid i Java, inkluderar intervallet inte 1.0själva numret.

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

int nextInt(int max)

Denna metod returnerar ett slumpmässigt heltal i intervallet [0, max). 0ingår i sortimentet, men maxär det inte.

Med andra ord, om du vill få ett slumptal i uppsättningen 1, 2, 3, 4, 5, 6måste du lägga till ett till det returnerade slumptalet:

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

int nextInt()

Denna metod liknar den föregående, men den tar inga parametrar. Så vad är intervallet för dess returvärden? Från -2 billiontill +2 billion.

Tja, för att vara exakt, från -2147483648till +2147483647.

long nextLong()

Denna metod liknar metoden nextInt(), men returvärdet kommer att falla någonstans i hela det möjliga intervallet longs.

boolean nextBoolean()

Denna metod returnerar ett slumpmässigt booleanvärde: falseeller true. Detta är mycket praktiskt när du behöver få en lång sekvens av slumpmässiga booleska värden.

void nextBytes(byte[] data)

Denna metod returnerar ingenting (eftersom returtypen är ) void. Istället fyller den den passerade arrayen med slumpmässiga värden. Detta är väldigt praktiskt när du behöver en stor buffert fylld med slumpmässiga data.

double nextGaussian()

Denna metod returnerar ett slumpmässigt reellt tal i intervallet 0.0- 1.0. Siffrorna är dock inte jämnt fördelade i detta intervall. Istället följer de en normalfördelning .

Värden nära mitten av intervallet ( 0.5) kommer att förekomma oftare än värden i slutet av intervallet.

Slumpmässig klass

I vårt fall kommer toppen av värdefördelningen att vara vid0.5