1. Псевдослучайни числа

Понякога програмистът се сблъсква с привидно прости задачи: „избере произволен филм от определен списък“, „избере победител от лотарията“, „разбърка плейлиста, когато потребителят разклати смартфона си“, „избере произволно число за шифроване на съобщение“ , и т.н. Във всеки случай разработчикът задава логичен въпрос: How да получите произволно число?

Всъщност получаването на наистина произволно число е доста трудно осъществимо. Всъщност е толкова трудно, че в някои компютри са вградени специални математически копроцесори, за да генерират числа, които отговарят на всички изисквания за истинска произволност.

Програмистите излязоха със собствено решение: псевдослучайни числа . Псевдослучайните числа са вид последователност, чиито числа изглеждат случайни. Въпреки това, чрез извършване на внимателен анализ, експертът може да открие определени модели в последователността. Такива числа не са подходящи за криптиране на секретни documentи, но са достатъчни за симулиране на хвърляне на зар в игра.

Има много алгоритми за генериране на поредица от псевдослучайни числа. Почти всички от тях генерират следващото произволно число въз основа на предишното число и някои допълнителни помощни числа.

Например, тази програма ще покаже 1000неповтарящи се числа:

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

Между другото, тук не говорим за псевдослучайни числа. Говорим за поредица от псевдослучайни числа. Гледайки едно число, е невъзможно да се каже дали е произволно or не.

Наистина има различни начини да получите произволно число:

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

2.Math.random()

В Java Mathкласът има специален метод, който връща произволно число. И Howто може би се досещате, методът се нарича random. Като цяло, ето How изглежда извикването на този метод:

Math.random()

Този метод не приема параметри и връща псевдослучайно реално число в диапазона от 0до 1. Самото число 1 не е включено в диапазона.

Пример:

Код Конзолен изход
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

Но Howво ще стане, ако този метод не е точно това, от което се нуждаете? Да предположим, че искате да напишете програма, която симулира хвърляне на шестстранен зар. Как получавате произволни цели числа в диапазона 1..6, instead of реални числа в диапазона 0..1?

Всъщност е доста просто.

Първо, трябва да картографирате диапазона [0, 1)върху [0, 6). За да направите това, просто умножете резултата, върнат с random()по 6. Разбира се, за да получите цели числа, трябва да закръглите:

Код Конзолен изход
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

Връща getRandomDieNumber()произволно цяло число в диапазона 0..5включително. Но няма да е номер в комплекта 1, 2, 3, 4, 5, 6. Това ще бъде номер в комплекта 0, 1, 2, 3, 4, 5.

Ако това, от което се нуждаете, са числа в набора 1, 2, 3, 4, 5, 6, тогава просто добавете едно към произволните числа:

Код Конзолен изход
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

Сега това е перфектно!



3. Randomклас

Java има специален Randomклас, който капсулира последователност от псевдослучайни числа. Можете да създадете няколко обекта от Randomкласа. Всеки от тези обекти ще генерира своя собствена последователност от псевдослучайни числа.

Това е супер интересен клас с много интересни методи. Да започнем с най-простото.

double nextDouble()

Този метод връща произволно реално число в диапазона 0.0- 1.0. Много е подобен на Math.random()метода. И не е чудно, тъй като Math.random()методът просто извиква nextDouble()метода на Randomобект.

float nextFloat()

Този метод е много подобен на nextDouble()метода, но върнатото произволно число е float. Също така се намира в диапазона 0.0- 1.0. И Howто винаги в Java, диапазонът не включва 1.0самото число.

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

int nextInt(int max)

Този метод връща произволно цяло число в диапазона [0, max). 0е включено в гамата, но maxне е.

С други думи, ако искате да получите произволно число в набора 1, 2, 3, 4, 5, 6, трябва да добавите едно към върнатото произволно число:

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

int nextInt()

Този метод е подобен на предишния, но не приема ниHowви параметри. И така, Howъв е диапазонът за неговите върнати стойности? От -2 billionдо +2 billion.

Ами, за да бъдем точни, от -2147483648до +2147483647.

long nextLong()

Този метод е подобен на nextInt()метода, но върнатата стойност ще попада някъде в целия възможен диапазон от longs.

boolean nextBoolean()

Този метод връща произволна booleanстойност: falseor true. Това е много удобно, когато трябва да получите дълга последователност от произволни булеви стойности.

void nextBytes(byte[] data)

Този метод не връща нищо (тъй като типът на връщане е void). Вместо това, той запълва подавания масив с произволни стойности. Това е много удобно, когато имате нужда от голям буфер, пълен с произволни данни.

double nextGaussian()

Този метод връща произволно реално число в диапазона 0.0- 1.0. Числата обаче не са равномерно разпределени в този диапазон. Вместо това те следват нормално разпределение .

Стойности близо до средата на диапазона ( 0.5) ще се срещат по-често от стойностите в краищата на диапазона.

Произволен клас

В нашия случай пикът на разпределението на стойността ще бъде при0.5