1. Псевдослучайные числа
Иногда программист сталкивается с простыми, казалось бы, задачами: «отобрать случайный фильм для вечернего просмотра из определенного списка», «выбрать победителя лотереи», «перемешать список песен при тряске смартфона», «выбрать случайное число для шифрования сообщения», и каждый раз у него возникает очень закономерный вопрос: а как получить это самое случайное число?
Вообще-то, если вам нужно получить «настоящее случайное число», сделать это довольно-таки трудно. Вплоть до того, что в компьютер встраивают специальные математические сопроцессоры, которые умеют генерировать такие числа, с выполнением всех требований к «истинной случайности».
Поэтому программисты придумали свое решение — псевдослучайные числа. Псевдослучайные числа — это некая последовательность, числа в которой на первый взгляд кажутся случайными, но специалист при детальном анализе сможет найти в них определенные закономерности. Для шифрования секретных документов такие числа не подойдут, а для имитации бросания кубика в игре — вполне.
Есть много алгоритмов генерации последовательности псевдослучайных чисел и почти все из них генерируют следующее случайное число на основе предыдущего и еще каких-то вспомогательных чисел.
Например, данная программа выведет на экран 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());
}
}
}
Кстати, мы говорим не о псевдослучайных числах, а именно о последовательности таких чисел. Т.к. глядя на одно число невозможно понять, случайное оно или нет.
Случайное число ведь можно получить разными способами:
public static int getRandomNumber()
{
return 4; // это точно случайное число (выкинул его с помощью кубиков)
}
2. Метод Math.random()
В Java у класса Math
есть специальный метод, который возвращает случайное число. И, как вы возможно догадываетесь, метод называется random
. Общий вид его вызова выглядит так:
Math.random()
Этот метод не принимает никаких параметров, но возвращает результат — псевдослучайное вещественное число в диапазоне от 0
до 1
. Единица при этом в диапазон не входит.
Пример:
Код | Вывод на экран |
---|---|
|
|
Но что, если вам этот метод не очень подходит, а вы хотите, допустим, написать программу, которая имитирует выбрасывание кубика с шестью гранями. Как получить случайные целые числа в диапазоне 1..6, а не вещественные в диапазоне 0..1?
Это на самом деле довольно просто.
Сначала нужно превратить диапазон [0,1)
в [0, 6)
. Для этого нужно просто умножить результат функции random()
на 6
. Ну а чтобы получить целые числа, нужно это все округлить:
Код | Вывод на экран |
---|---|
|
|
Функция getRandomDiceNumber()
возвращает случайное целое число из диапазона 0..5
включительно. Только это будут не числа из набора 1,2,3,4,5,6
, а числа из набора 0,1,2,3,4,5
.
Если требуются именно числа из набора 1,2,3,4,5,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
. И, как всегда, в 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()
Этот метод аналогичен предыдущему, но не принимает никаких параметров. Тогда в каком же диапазоне он выдает числа? От -2 миллиарда
до +2 миллиарда
.
Ну или если точнее, от -2147483648
до +2147483647
.
Метод long nextLong()
Этот метод аналогичен методу nextInt()
, только возвращаемое значение будет из всего возможного диапазона значений типа long
.
Метод boolean nextBoolean()
Этот метод возвращает случайное значение типа boolean
: false
или true
. Очень удобно, если нужно получить длинную последовательность случайных логических значений.
Метод void nextBytes(byte[] data)
Этот метод ничего не возвращает (тип void
). Вместо этого он заполняет переданный в него массив случайными значениями. Очень удобно, если нужен большой буфер, заполненный случайными данными.
Метод double nextGaussian()
Этот метод возвращает случайное вещественное число в диапазоне 0.0
— 1.0
. Вот только числа в этом диапазоне распределены не равномерно, а подчиняются нормальному распределению.
Числа ближе к середине диапазона (0.5
) будут выпадать чаще, чем значение по краям диапазона.
Пик значений в нашем случае придется на 0.5
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ