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



Комментарии (520)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Valery Уровень 12
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 Уровень 24
7 декабря 2025
Немного непонятно, зачем обрабатывать в Magic Ball событие "иначе вернуть null" ведь в заданном диапазоне для random (если он корректно задан), и так не будет числа, которого не должно быть.
Dmitry Уровень 10
9 января 2026
Тоже задался этим вопросом
Viktoriko Уровень 19
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 Уровень 19
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];
    } 
Pukidmi Уровень 7
27 октября 2025
Не стоит воспринимать информацию из второй и третьей главы как вариативность. Math.random() с приведением к целому числу - неэффективный пример, стоило об этом написать в лекции
Grigoryvvv Уровень 13 Expert
15 октября 2025
15.10.2025 / 9 уровень
Aleksandr Уровень 10
22 сентября 2025
Для выполнения условия добавил оператор if-else

public static String getPrediction() {
        Random r = new Random();
        int x = r.nextInt(8);
        String[] array = {CERTAIN, DEFINITELY, MOST_LIKELY, OUTLOOK_GOOD, ASK_AGAIN_LATER, TRY_AGAIN, NO, VERY_DOUBTFUL};//напишите тут ваш код
        if (x >= 0 & x <= 7)
        {
            return array[x];
        } else {
            return null;
        }
    }
Алексей Уровень 12
12 сентября 2025
public static String getPrediction() { Random r = new Random(); int rnd = r.nextInt(8); return rnd >= 0 && rnd < 8 ? (new String[]{CERTAIN, DEFINITELY, MOST_LIKELY, OUTLOOK_GOOD, ASK_AGAIN_LATER, TRY_AGAIN, NO, VERY_DOUBTFUL})[rnd] : null; }
Maksim29AM Уровень 12
1 сентября 2025

 Random r = new Random();
        int x = r.nextInt(8);
        String text = switch (x) {
            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;
        };
        return text;
Ivan Pesterev Уровень 37
23 сентября 2025
где breake'и?? он во все кейсы зайдет
Ripper Уровень 12
1 сентября 2025
как вам такой вариант? вроде неплохо

public static String getPrediction() {
        String[] optionOfPrediction = {CERTAIN, DEFINITELY, MOST_LIKELY,
        OUTLOOK_GOOD, ASK_AGAIN_LATER, TRY_AGAIN, NO, VERY_DOUBTFUL};
        
        int result = new Random().nextInt(optionOfPrediction.length);
        
        if(result >= 0 && result <=7) {
            String option = "default";
            for(int i = 0; i < optionOfPrediction.length; i++) {
                if (result == i)
                    option = optionOfPrediction[i];
            }
            return option;
        }
        else return null;
    }
LorMag Уровень 38
2 сентября 2025
Можно сразу обратиться по индексу массива optionOfPrediction без итерации в форике. В таком случае, после генерации значения будет проверка на if, если result попадает, то возвращаем optionOfPrediction[result]