JavaRush /Курсы /Java Syntax Pro /Случайные числа в Java

Случайные числа в Java

Java Syntax Pro
8 уровень , 1 лекция
Открыта

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. Единица при этом в диапазон не входит.

Пример:

Код Вывод на экран
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

Но что, если вам этот метод не очень подходит, а вы хотите, допустим, написать программу, которая имитирует выбрасывание кубика с шестью гранями. Как получить случайные целые числа в диапазоне 1..6, а не вещественные в диапазоне 0..1?

Это на самом деле довольно просто.

Сначала нужно превратить диапазон [0,1) в [0, 6). Для этого нужно просто умножить результат функции random() на 6. Ну а чтобы получить целые числа, нужно это все округлить:

Код Вывод на экран
public class Main
{
   public static int getRandomDiceNumber()
   {
      return (int) (Math.random() * 6);
   }

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

Функция getRandomDiceNumber() возвращает случайное целое число из диапазона 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 getRandomDiceNumber()
   {
      return (int) (Math.random() * 6) + 1;
   }

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

Вот теперь идеально!



3. Класс Random

В Java есть специальный класс Random, который инкапсулирует в себе последовательность псевдослучайных чисел. Можно создать несколько объектов класса Random, и каждый из этих объектов будет генерировать свою последовательность псевдослучайных чисел.

Это очень интересный класс, и у него есть много интересных методов. Начнем с самых простых:

Метод double nextDouble()

Этот метод возвращает случайное вещественное число в диапазоне 0.01.0. Очень похоже на метод Math.random(). И ничего удивительного, ведь метод Math.random() просто вызывает метод nextDouble() у объекта типа Random.

Метод float nextFloat()

Метод очень похож на метод nextDouble(), только возвращаемое случайное число типа float. Оно также лежит в диапазоне 0.01.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.01.0. Вот только числа в этом диапазоне распределены не равномерно, а подчиняются нормальному распределению.

Числа ближе к середине диапазона (0.5) будут выпадать чаще, чем значение по краям диапазона.

Класс Random

Пик значений в нашем случае придется на 0.5



Комментарии (525)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
FromZeroToHero Уровень 35
1 марта 2026
самое главное не написали - формулы получить случайное вещественное число от min до max с помощью Math.random():

Math.random(max - min) + min;
получить случайное целое число от min до max: - с помощью Math.random():

(int) (Math.random() * (max - min + 1)) + min;
- с помощью класса Random:

Random random = new Random();
int r = random.nextInt(max - min + 1) + min;
Карен Абазов Уровень 28
24 февраля 2026
Для чего люди копипастят в коменты правильные решения с самой задачи?)))
Saruman71 Уровень 19
10 февраля 2026
Пример решения через тернарный оператор. public static String getPrediction() { Random r = new Random(); int x = r.nextInt(8); return x == 0 ? CERTAIN : x == 1 ? DEFINITELY : x == 2 ? MOST_LIKELY : x == 3 ? OUTLOOK_GOOD : x == 4 ? ASK_AGAIN_LATER : x == 5 ? TRY_AGAIN : x == 6 ? NO : x == 7 ? VERY_DOUBTFUL : null; }
Win32Trojan Уровень 13
11 июля 2026
Тебя будут ненавидеть программисты, которые будут изучать твой код, т.к. это плохо читается.
Anonymous #3466115 Уровень 17
31 января 2026
В правильном решении предлагается так: public static String getPrediction() { int random = new Random().nextInt(8); // остальной код } Т.е. каждый раз при вызове метода будет создаваться экземпляр класса Random, но это плохое решение с точки зрения экономии ресурсов, т.к. создание объекта это дорогая операция и + если в таком виде часто будет вызываться метод getPrediction() то разные экземпляры класса Random могут генерировать одинаковые числа, что может снизить качество "случайности". Лучше один раз создать экземпляр класса Random и сделать его статическим полем нашего класса MagicBall: private static final Random random = new Random(); Тогда в методе обращаться уже к нашему статическому полю: public static String getPrediction() { int random = random.nextInt(8); // остальной код } Ну и постараться запомнить эту тонкость)
Valery Уровень 4
17 декабря 2025
Добрый день, читатели, варианты через массив показанные ниже другими авторами выглядят лучше правильного решения, если рассматривать решение "на вырост" значений. Могу предложить альтернативу решения конкретно этой задачи для бОльшего кругозора и о котором будут говорить, скорее всего дальше на курсе, правда неизвестно когда, более читабельное решение if-else (спойлер):

public class MagicBall {
    private static final String CERTAIN = "Бесспорно";
    private static final String DEFINITELY = "Определённо да";
    private static final String MOST_LIKELY = "Вероятнее всего";
    private static final String OUTLOOK_GOOD = "Хорошие перспективы";
    private static final String ASK_AGAIN_LATER = "Спроси позже";
    private static final String TRY_AGAIN = "Попробуй снова";
    private static final String NO = "Мой ответ — нет";
    private static final String VERY_DOUBTFUL = "Весьма сомнительно";

    public static String getPrediction() {
        return switch (new Random().nextInt(8)) {
            case 0 -> CERTAIN;
            case 1 -> DEFINITELY;
            case 2 -> MOST_LIKELY;
            case 3 -> OUTLOOK_GOOD;
            case 4 -> ASK_AGAIN_LATER;
            case 5 -> TRY_AGAIN;
            case 6 -> NO;
            case 7 -> VERY_DOUBTFUL;
            default -> null;
        };
    }
}

А также хочу посоветовать очень полезную статью на эту тему: https://javarush.com/groups/posts/operator-switch-v-java
Nik Уровень 10
15 декабря 2025
public class MagicBall { private static final String CERTAIN = "Бесспорно"; private static final String DEFINITELY = "Определённо да"; private static final String MOST_LIKELY = "Вероятнее всего"; private static final String OUTLOOK_GOOD = "Хорошие перспективы"; private static final String ASK_AGAIN_LATER = "Спроси позже"; private static final String TRY_AGAIN = "Попробуй снова"; private static final String NO = "Мой ответ — нет"; private static final String VERY_DOUBTFUL = "Весьма сомнительно"; public static String[] phrases = new String[]{CERTAIN, DEFINITELY, MOST_LIKELY, OUTLOOK_GOOD, ASK_AGAIN_LATER, TRY_AGAIN, NO, VERY_DOUBTFUL}; public static String getPrediction() { Random random = new Random(); int b = random.nextInt(8); for (int i = 0; i < phrases.length; i++) { if (b == i) { return phrases[i]; } } return null; } }
Denis Pereladov Уровень 40
7 декабря 2025
Немного непонятно, зачем обрабатывать в Magic Ball событие "иначе вернуть null" ведь в заданном диапазоне для random (если он корректно задан), и так не будет числа, которого не должно быть.
Dmitry Уровень 29
9 января 2026
Тоже задался этим вопросом
Viktoriko Уровень 20
10 ноября 2025
Очень странные решения иной раз можно встретить при нажатии на кнопку с сомнительным названием "Правильное решение". Почему сомнительное? Да потому что оно говорит, что как будто все остальные решения неправильные) Но это вкусовщина. Теперь к сути. Ощущение, что этот код писал джун, ну или студент. Я понимаю, что большая часть курса ещё впереди, но, исходя из пройденного материала, можно использовать более корректное, читабельное решение текущей задачи. Необходимо ведь учить правильно. Показыввать как это должно писаться, а не просто решаться. Если такое решение будет в продакшене, то это будет очень печальная картина, показывающая уровень всего проекта. Предлагаю разобраться 1. Откуда проверка в последнем else, что если ни одно число не подошло (от 0 до 7), то возвращать null? Для чего? Метод Random.nextInt(int) возвращает случайное целое число, начиная с нуля и до переданного значения. Если вы туда передали аргументом число 8, то прошу объясните в каких ситуациях мы достигнем обработки последнего else. По средней статистике такой кейс может отработать примерно никогда. Так зачем излишняя обработка? 2. Уважаемые кураторы/преподаватели/лекторы курса. Вы хоть раз писали такую портянку в своём проекте? Даже если это пет проект. А если надо было бы проверять 90 значений, а если 900? Я понимаю, что ранее в Китае платили за количество символов в коде, и там - это очень крутое решение, но у нас другая цель - работающий, оптимальный, лаконичный и читаемый код. Откуда портянка эта не пойму... Исходя из пройденного ранее материала мы знаем, что 1. Random.nextInt(8) вернет целое число от 0 до 7 включительно. 2. Есть такая структура как массив. 3. Можно все варианты поместить в массив строк. 4. Можно обратиться к элементу по индексу массива, которые по счастливой случайности в строгом диапазоне от нуля до 7 включительно. Так зачем эта непонятная конструкция (if -> else if -> else), если есть более читаемое решение?
Viktoriko Уровень 20
10 ноября 2025
ВНИМАНИЕ! Ниже будет приведено решение, которое НЕ проходит проверку, так как оно не обрабатывает кейс, когда выпадет число 8 (которое по условию выпасть не может)

public static String getPrediction() {
        String[] answers = {CERTAIN, DEFINITELY, MOST_LIKELY, OUTLOOK_GOOD, ASK_AGAIN_LATER, TRY_AGAIN, NO, VERY_DOUBTFUL};
        Random random = new Random();
        int randomNumber = random.nextInt(answers.length);

        return answers[randomNumber];
    }
Ниже приведено решение, проходящее проверку, по причине обработки невозможного кейса, который заложили в проверку

public static String getPrediction() {
        String[] answers = {CERTAIN, DEFINITELY, MOST_LIKELY, OUTLOOK_GOOD, ASK_AGAIN_LATER, TRY_AGAIN, NO, VERY_DOUBTFUL};
        Random random = new Random();
        int randomNumber = random.nextInt(8);
        return randomNumber > 7 || randomNumber < 0 ? null : answers[randomNumber];
    } 
hidden #6416165 Уровень 7
27 октября 2025
Не стоит воспринимать информацию из второй и третьей главы как вариативность. Math.random() с приведением к целому числу - неэффективный пример, стоило об этом написать в лекции
Grigoryvvv Уровень 18 Expert
15 октября 2025
15.10.2025 / 9 уровень