JavaRush /Блог /Архив info.javarush /Генерация случайного числа в заданном диапазоне
L2CCCP
9 уровень

Генерация случайного числа в заданном диапазоне

Статья из группы Архив info.javarush
Привет по ту сторону экрана. Любой из нас рано или поздно встречается с необходимостью генерировать случайное число в заданном нами диапазоне будь то вещественное или целое число. Генерация случайного числа в заданном диапазоне - 1Для чего? На самом деле это не важно, это может быть функция для расчета шанса для запуска какого нибудь события, получение случайного множителя или любого другая. Итак, для чего это нужно разобрались, а именно для чего угодно :) На самом деле методов получения псевдослучайного числа очень много, я же приведу пример с классом Math, а именно с методом random(); Что же мы имеем? Вызов метода Math.random() возвращает псевдослучайное вещественное число (double) из диапазона [0;1), то есть, от 0 до 1 исключая 1, а значит максимальное число в диапазоне это 0.99999999999... Хорошо, мы получили псевдослучайное число, но если нам нужен свой диапазон? К примеру, нам нужно псевдослучайное число из диапазона [0;100)? Пишем код:


	public static void main(String... args)
	{
		final double max = 100.; // Максимальное число для диапазона от 0 до max
		final double rnd = rnd(max);

		System.out.println("Псевдослучайное вещественное число: " + rnd);
	}

	/**
	 * Метод получения псевдослучайного вещественного числа от 0 до max (исключая max);
	 */
	public static double rnd(final double max)
	{
		return Math.random() * max;
	}
Получилось не плохо, но max (в нашем случае) мы все равно не получим. Для того чтобы получить случайное число в диапазоне [0;100] нам необходимо прибавить к нашему max 1, а затем преобразовать в целое число типа int или long (зависит от диапазонов которые Вы будете использовать). Пишем код:

	public static void main(String... args)
	{
		final int max = 100; // Максимальное число для диапазона от 0 до max
		final int rnd = rnd(max);

		System.out.println("Псевдослучайное целое число: " + rnd);
	}

	/**
	 * Метод получения псевдослучайного целого числа от 0 до max (включая max);
	 */
	public static int rnd(int max)
	{
		return (int) (Math.random() * ++max);
	}
Примечание: Как видите переменная max была инкрементирована префиксной формой. (Если Вы не знаете что это советую почитать мою статью) Отлично, мы получили то что хотели, но если нам нужен диапазон не от 0, а к примеру [10;75] Пишем код:

	public static void main(String... args)
	{
		final int min = 10; // Минимальное число для диапазона
		final int max = 75; // Максимальное число для диапазона
		final int rnd = rnd(min, max);

		System.out.println("Псевдослучайное целое число: " + rnd);
	}

	/**
	 * Метод получения псевдослучайного целого числа от min до max (включая max);
	 */
	public static int rnd(int min, int max)
	{
		max -= min;
		return (int) (Math.random() * ++max) + min;
	}
Разбор кода из метода rnd:

Минимальное число диапазона = 10;
Максимальное число диапазона = 75;
max -= min; // Отнимаем от максимального значения минимальное для получения множителя псевдослучайного вещественного числа.
Максимальное число после расчета равно 65 Псевдослучайное вещественное число (к примеру) равно 0.18283417347179454 (Был получен при вызове Math.random()). Максимальное число перед умножением было инкрементировано префиксной формой. Максимальное число теперь 66 Умножаем 0.18283417347179454 на 66. Результат умножения равен 12.06705544913844. Преобразовываем результат умножения максимального числа на псевдослучайное вещественное число к типу целого числа int. Прибавляем минимальное число к преобразованному результату который равен 12. Возвращаем результат: 22 Как видно из разбора, даже если псевдослучайное вещественное число будет равно нулю, то мы вернем наш минимум в результате сложения нашего минимального числа с результатом умножения. Надеюсь для Вас это было полезно и познавательно. Успехов в освоении Java ;) Еще пару моих статей: Что такое инкрементирование и декрементирование Оператор деления по модулю
Комментарии (17)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
LindX Уровень 12
27 августа 2021
У автора просто талат писать статьи с максимальным количеством воды. `Math.random()`:**double** - возвращает псевдослучайное вещественное число в диапазоне `[0;0.99999999999...]` т.е. от 0 до 1 исключая 1. ### EX: Псевдослучайное число из диапазона `[0;100]`

// Получим псевдослучайное вещественное число от 0 до 100 (исключая 100);
final int max = 100;
System.out.println(Math.random() * max);
Для того чтобы получить случайное число в диапазоне `[0;100]` нам необходимо прибавить к `max` 1, а затем преобразовать в целое число типа `int` или `long` (зависит от диапазонов которые Вы будете использовать).

// Получим псевдослучайное целое число от 0 до max (включая max);
final int max = 100;
System.out.println((int)Math.random() * ++max);
### EX: Псевдослучайное число из диапазона `[10;75]`

// Получим псевдослучайное целое число от min до max (включая max);
final int min = 10; // Минимальное число для диапазона
final int max = 75; // Максимальное число для диапазона

max -= min; // Отнимаем для получения множителя псевдослучайного вещественного числа.
   
System.out.println( ((int) (Math.random() * ++max)) + min);
Пример: Максимальное число после расчета равно 65 1. При вызове `Math.random()` получаем : `0.18283417347179454` 2. Перед умножением, максимальное число инкрементируем префиксной формой. Максимальное число теперь `66` 3. Умножаем `0.18283417347179454` на `66` получаем `12.06705544913844` 4. Преобразовываем результат умножения `12.06705544913844` к типу целого числа `int`. Получаем `12` 5. К преобразованному результату прибавляем минимальное число 10. Возвращаем результат: `22` > Даже если псевдослучайное вещественное число будет равно 0, то мы вернем наш минимум в результате сложения минимального числа с результатом умножения.
Herr Ives Уровень 30
15 декабря 2019
попробовал использовать данный способ, почему то при переборе от 0 до 20 добавляется меньшее количество элементов. пришлось использовать конструкцию while HashSet.size<20
Antony.Glim Уровень 36 Expert
18 марта 2019
Не рассмотрен случай, когда нужно получить число, которое входит и в отрицательный диапазон тоже. rnd(-100, 100)

    /**
     * Функция вернет случайное число из указанного диапазона
     * @param min - включительно. min должно быть отрицательным числом
     * @param max - включительно
     * @return - псевдослучайное целое число
     */
    public static int rnd(int min, int max){
        int diapason = max + Math.abs(min) + 1;
        return  (int) (Math.random() * diapason) - max;
    }
alexnjc Уровень 31
11 июня 2015
Кстати, с помощью рандома можно генерировать пароли.
Простой пример:

import java.util.Random;

public class PasswordGenerator {
    public static String generate(int from, int to) {
        String pass  = "";
        Random r     = new Random();
        int cntchars = from + r.nextInt(to - from + 1);

        for (int i = 0; i < cntchars; ++i) {
            char next = 0;
            int range = 10;

            switch(r.nextInt(3)) {
                case 0: {next = '0'; range = 10;} break;
                case 1: {next = 'a'; range = 26;} break;
                case 2: {next = 'A'; range = 26;} break;
            }

            pass += (char)((r.nextInt(range)) + next);
        }

        return pass;
    }

    public static void main(String argv[]) {
        String pass = generate(8, 12);
        System.out.println(pass);
    }
}
Izhak Уровень 22
9 июня 2015
stackoverflow.com/questions/363681/generating-random-integers-in-a-range-with-java


int r = (new Random()).ints(5,67).iterator().nextInt();

(Можно задать итератор и по нему путешествовать)
Для мультипоточных
docs.oracle.com/javase/tutorial/essential/concurrency/threadlocalrandom.html

int r = ThreadLocalRandom.current().nextInt(4, 77);
sem_top7 Уровень 32
8 июня 2015
А числа то не случайные :) Может автор расскажет почему эти числа называются псевдослучайными? И как же все таки добиться случайных чисел?
timurnav Уровень 21
8 июня 2015
Предлагаю использовать не приведение к целочисленному типу с инкрементом, а воспользоваться методом того же класса Math.round(n) — стандартное округление в сторону ближнего своего :)