Note that this approach is more biased and less efficient than a nextInt
approach, https://stackoverflow.com/a/738651/360211
One standard pattern for accomplishing this is:
Min + (int)(Math.random() * ((Max - Min) + 1))
The Java Math library function Math.random() generates a double value in the range [0,1)
. Notice this range does not include the 1.
In order to get a specific range of values first, you need to multiply by the magnitude of the range of values you want covered.
Math.random() * ( Max - Min )
This returns a value in the range [0,Max-Min)
, where ‘Max-Min’ is not included.
For example, if you want [5,10)
, you need to cover five integer values so you use
Math.random() * 5
This would return a value in the range [0,5)
, where 5 is not included.
Now you need to shift this range up to the range that you are targeting. You do this by adding the Min value.
Min + (Math.random() * (Max - Min))
You now will get a value in the range [Min,Max)
. Following our example, that means [5,10)
:
5 + (Math.random() * (10 - 5))
But, this still doesn’t include Max
and you are getting a double value. In order to get the Max
value included, you need to add 1 to your range parameter (Max - Min)
and then truncate the decimal part by casting to an int. This is accomplished via:
Min + (int)(Math.random() * ((Max - Min) + 1))
And there you have it. A random integer value in the range [Min,Max]
, or per the example [5,10]
:
5 + (int)(Math.random() * ((10 - 5) + 1))
При разработке приложений часто нужно генерировать случайные числа. Java предоставляет для этого классы java.lang.Math и java.util.Random. В этой статье я расскажу о нескольких способах генерации случайных чисел и приведу конкретные примеры реализации.
- Генерация случайных чисел с помощью класса Math
- Случайные числа в заданном диапазоне
- Случайное двойное число в заданном диапазоне
- Случайное целое число в заданном диапазоне
- Генерация случайных чисел с помощью класса Random
- Генерируем случайное число в Java 8 – особенности
- Заключение
Чтобы сгенерировать случайное число Java предоставляет класс Math, доступный в пакете java.util. Этот класс содержит статичный метод Math.random(), предназначенный для генерации случайных чисел типа double .
Метод random( ) возвращает положительное число большее или равное 0,0 и меньшее 1,0. При вызове данного метода создается объект генератора псевдослучайных чисел java.util.Random.
Math.random() можно использовать с параметрами и без. В параметрах задается диапазон чисел, в пределах которого будут генерироваться случайные значения.
Пример использования Math.random():
public static double getRandomNumber(){ double x = Math.random(); return x; }
Метод getRandomNumber( ) использует Math.random() для возврата положительного числа, которое больше или равно 0,0 или меньше 1,0 .
Результат выполнения кода:
Double between 0.0 and 1.0: SimpleRandomNumber = 0.21753313144345698
Для генерации случайных чисел в заданном диапазоне необходимо указать диапазон. Синтаксис:
(Math.random() * ((max - min) + 1)) + min
Разобьем это выражение на части:
- Сначала умножаем диапазон значений на результат, который генерирует метод random().Math.random() * (max – min)возвращает значение в диапазоне [0 , max- min], где max не входит в заданные рамки. Например, выражение Math.random()*5 вернет значение в диапазоне [0 , 5], в который 5 не входит.
- Расширяем охват до нужного диапазона. Это делается с помощью минимального значения.
(Math.random() * ( max - min )) + min
Но выражение по-прежнему не охватывает максимальное значение.
- Чтобы получить максимальное значение, прибавьте 1 к параметру диапазона (max – min). Это вернет случайное число в указанном диапазоне.
double x = (Math.random()*((max-min)+1))+min;
Существуют различные способы реализации приведенного выше выражения. Рассмотрим некоторые из них.
По умолчанию метод Math.random() при каждом вызове возвращает случайное число типа double . Например:
public static double getRandomDoubleBetweenRange(double min, double max){ double x = (Math.random()*((max-min)+1))+min; return x; }
Вы можете вызвать предыдущий метод из метода main, передав аргументы, подобные этому.
System.out.println("Double between 5.0 and 10.00: RandomDoubleNumber = "+getRandomDoubleBetweenRange(5.0, 10.00));
Результат.
System.out.println("Double between 5.0 and 10.00: RandomDoubleNumber = "+getRandomDoubleBetweenRange(5.0, 10.00));
Пример генерации случайного целочисленного значения в указанном диапазоне:
public static double getRandomIntegerBetweenRange(double min, double max){ double x = (int)(Math.random()*((max-min)+1))+min; return x; }
Метод getRandomIntegerBetweenRange() создает случайное целое число в указанном диапазоне. Так как Math.random() генерирует случайные числа с плавающей запятой, то нужно привести полученное значение к типу int. Этот метод можно вызвать из метода main, передав ему аргументы следующим образом:
System.out.println("Integer between 2 and 6: RandomIntegerNumber = "+getRandomIntegerBetweenRange(2,6));
Результат.
Integer between 2 and 6: RandomIntegerNumber = 5
Примечание. В аргументах также можно передать диапазон отрицательных значений, чтобы сгенерировать случайное отрицательное число в этом диапазоне.
Класс java.util.Random можно применять для генерации случайных чисел различных типов: int, float, double, long и boolean .
Для этого сначала создайте экземпляр класса Random, а затем вызовите один из методов генератора случайных значений: nextInt( ), nextDouble( ) или nextLong( ).
Метод nextInt( ) класса Random принимает граничное целое число и возвращает случайное значение int от 0 (включительно) до указанного предела (не включая).
Пример использования метода nextInt( ):
public static int generateRandomInt(int upperRange){ Random random = new Random(); return random.nextInt(upperRange); }
Пример использования метода nextInt ( ) для генерации целого числа в заданном диапазоне:
public static int generateRandomIntIntRange(int min, int max) { Random r = new Random(); return r.nextInt((max - min) + 1) + min; }
Методы nextFloat ( ) и nextDouble( ) позволяют генерировать числа с плавающей запятой, а также значения типа double в диапазоне от 0,0 до 1,0.
Код для использования обоих методов:
public static double generateRandomDouble(){ Random random = new Random(); return random.nextDouble(); } public static float generateRandomFloat(){ Random random = new Random(); return random.nextFloat(); }
В Java 8 был представлен новый метод класса java.util.Random – ints(). Он возвращает неограниченный поток псевдослучайных значений int. Данный метод позволяет указать диапазон чисел, задав минимальное и максимальное значения.
Пример использования метода Random.ints() для генерации случайных целочисленных значений в указанном диапазоне:
public static int getRandomNumberInts(int min, int max){ Random random = new Random(); return random.ints(min,(max+1)).findFirst().getAsInt(); }
Метод getRandomNumberInts( ) генерирует поток случайных целых чисел от min(включительно) и до max (не входит в диапазон).
Метод ints( ) создает IntStream, поэтому будет вызвана функция findFirst( ). Она возвращает объект OptionalInt , который описывает первый элемент этого потока. Затем код вызывает метод getAsInt( ), чтобы вернуть значение int в OptionalInt.
Пример использования метода Random.ints() для генерации потока случайных целочисленных значений:
public static void getStreamOfRandomInts(int num) { Random random = new Random(); random.ints(num).sorted().forEach(System.out::println); }
Код для вызова предыдущего метода:
System.out.println("Random int stream: RandomIntStreamofSize = "); RandomDemo.getStreamOfRandomInts(5);
Результат работы приведенного выше кода:
Random int stream: RandomIntStreamofSize = -1861317227 -1205557317 453883217 762357682 1725970934
Пример использования метода Random.ints() для генерации потока из диапазона случайных целочисленных значений:
public static void getStreamOfRandomIntsWithRange(int num, int min, int max) { Random random = new Random(); random.ints(num,min, max).sorted().forEach(System.out::println); }
Код для вызова приведенного выше метода:
System.out.println("Random int stream of specified size in range: RandomIntStreamofSizeInRange = "); RandomDemo.getStreamOfRandomIntsWithRange(5,0,10);
Результат работы предыдущего примера:
Random int stream of specified size in range: RandomIntStreamofSizeInRange = 2 2 3 4 6
Кроме ints( ) существует еще несколько методов, которые были добавлены к классу Random в Java 8. Они могут возвращать последовательный поток случайных чисел. Это:
- LongStream longs( );
- DoubleStream doubles( ).
Класс java.util.Random реализует линейный конгруэнтный генератор (LCG). Он отличается быстротой работы. Но при этом он не подходит для использования в режиме реального времени. Например, для генерации уникального идентификатора сессии на сервере, в научных экспериментах, криптографии лотереях и розыгрышах.
Данная статья:
- написана командой Vertex Academy. Надеемся, что она Вам будет полезна. Приятного прочтения!
- это одна из статей из нашего “Самоучителя по Java”
Генерация случайных чисел в Java – важная и нужная тема. Действительно, она Вам понадобится неисчислимое количество раз.
Например:
- при заполнении массива случайными числами
- при перетасовке колоды карт
- при выборе случайного элемента из последовательности
- и т.д.
Давайте же разберемся с этой темой.
Существует несколько способов как сгенерировать случайное число. В этой статье мы рассмотрим генерацию чисел с помощью Math.random()
В библиотеке классов Java есть пакет java.lang, у которого есть класс Math, а у класса Math есть метод random(). См. картинку ниже в помощь.
Так вот, при каждом вызове Math.random() c помощью специального алгоритма (за определенной инструкцией) генерируется случайное число. Можно ли предсказать какое число будет сгенерировано? Теоретически это возможно, но это очень трудно сделать. А поскольку все-таки существует небольшая вероятность предсказать, какое же число будет сгенерировано алгоритмом, такие числа принято называть не случайными, а псевдослучайными.
Вы должны знать 3 момента:
1. По умолчанию Math.random() генерирует случайные вещественные числа из промежутка [0;1), то есть от нуля включительно до 1 исключительно.
“До 1 исключительно” – это значит, что Math.random() не может сгенерировать число 1. Разве что 0,999 – то есть любое число меньше 1.Попробуйте запустить на своем компьютере вот этот код и сами увидите, что в консоль будут выводиться вещественные числа от 0 до любого числа, меньше 1.
public class Test { public static void main(String[] args){ double a = Math.random(); System.out.println (a); } } |
Так что если Вам необходимо сгенерировать случайные числа из промежутка [0;1), Вы уже знаете как это сделать.
2. А что если нам необходимо сгенерировать числа из другого диапазона, отличного от [0;1)?
Легко! Давайте формально запишем наш диапазон: [a;b). То есть нижняя граница а, верхняя b. Тогда для генерации вещественных чисел в заданном диапазоне нужно записать следующее:
( Math.random() * (b-a) ) + a
Рассмотрим на примерах.
Пример №1
Итак, чтобы получить случайное вещественное число из промежутка [0;3), (3 исключительно), используем:
public class Test { public static void main(String[] args){ double a = Math.random()*3; System.out.println(a); } } |
Как это работает?
Диапазон [0;1) умножается на 3. Соответственно,
Нижняя граница: 0*3 = 0
Верхняя граница: 1*3 = 3
Получаем диапазон [0;3)
Если применить нашу формулу, получим:
( Math.random() * (3 – 0) ) + 0 => Math.random() * 3
Что и отображено в программе.
Пример №2
Допустим, нам необходимо получить число с плавающей точкой в интервале [ 2; 3) (3 исключительно)
public class Test { public static void main(String[] args){ double a = Math.random()+2; System.out.println(a); } } |
Как это работает?
К диапазону [0;1) прибавляем 2. Соответственно,
Нижняя граница: 0 + 2 = 2
Верхняя граница: 1 + 2 = 3
Получаем диапазон [2;3)
Согласно формуле:
( Math.random() * (3 – 2) ) + 2 => Math.random() * 1 + 2 => Math.random() + 2
Пример №3
Допустим, нам необходимо получить вещественное число в интервале [ 20; 60) (60 исключительно)
public class Test { public static void main(String[] args){ double a = 20 + Math.random()*40; System.out.println(a); } } |
Как это работает?
Шаг №1: Диапазон [0;1) умножается на 40. Соответственно,
Нижняя граница: 0*40 = 0
Верхняя граница: 1*40 = 40
Получаем диапазон [0;40)
Шаг №2: К диапазону [0;40) прибавляем 20. Соответственно,
Нижняя граница: 0 + 20 = 20
Верхняя граница: 40 + 20 = 60
Получаем диапазон [20;60)
Если просто подставить в формулу, то получим:
( Math.random() * (60 – 20) ) + 20 => Math.random() * 40 + 20
Пример №4
Вещественное число в интервале[ -100; +100) (100 исключительно)
public class Test { public static void main(String[] args){ double a = Math.random()*200 – 100; System.out.println(a); } } |
По формуле:
( Math.random() * (100 – (-100)) ) + (-100) => Math.random() * 200 – 100
3. А как сгенерировать целочисленное значение?
Пример №5
Представим, что нам необходимо сгенерировать число в интервале [0;2]. Обратите внимание, что после 2 скобка квадратная, а не круглая. Это значит, что нас интересует, чтоб диапазон включал в себя число 2. Как это сделать? Вот так:
public class Test { public static void main(String[] args){ int a = (int) ( Math.random() * 3 ); } } |
Как это работает?
Шаг №1: Диапазон [0;1) умножаем на 3. Соответственно,
Нижняя граница: 0*3 =0
Верхняя граница:1*3 =3
Получили диапазон [0;3). Скобка после числа 3 круглая. Это значит, что 3 не входит в диапазон, то есть максимальное число, которое может быть сгенерировано в этом диапазоне это 2,999. Одним словом – мы имеем дело с вещественными (дробными) числами.
Шаг №2: Поэтому применяем (int) перед Math.random()*3. Дробная часть отсекается и мы получаем диапазон [0;2]
Если рассмотреть нашу формулу, то она не очень сильно поменяется.
В случае, если вещественное число, и верхний диапазон включает b – [a;b] :
( Math.random() * (b – a + 1) + a
Если еще и только целые числа:
(int)(( Math.random() * (b – a + 1) + a)
Пример №6
Если необходимо сгенерировать число из интервала [3;4]. Обратите внимание, что после 4 скобка квадратная. Это значит, что нас интересует, чтоб диапазон включал в себя число 4. Как это сделать? Вот так:
public class Test { public static void main(String[] args){ int a = 3 + (int) ( Math.random() * 2 ); } } |
Как это работает?
Шаг №1: Диапазон [0;1) умножаем на 2. Соответственно,
Нижняя граница:0*2 =0
Верхняя граница:1*2 =2
Получили диапазон [0;2). Скобка после числа 2 круглая. Это значит, что 2 не входит в диапазон, то есть максимальное число, которое может быть сгенерировано в этом диапазоне это 1,999. А это значит, что мы имеем дело с вещественным (дробным) числом.
Шаг №2: Поэтому применяем (int) перед Math.random()*2. Дробная часть отсекается и мы получаем диапазон [0;1]. Обратите внимание – диапазон уже по число 1 включительно.
Шаг №3: Далее к диапазону [0;1] прибавляем 3. Соответственно,
Нижняя граница: 0+3 = 3
Верхняя граница: 1+3 =4
Получили новый диапазон [3;4]
По формуле:
(int)(Math.random() * (4 – 3 + 1) + 3) => (int)(Math.random() *2 + 3)
Пример №7
Целочисленное значение в интервале [ -100; +100](100 включительно):
public class Test { public static void main(String[] args){ int a = (int) (Math.random()*(200+1)) – 100; System.out.println(a); } } |
Пример №8
Целочисленное значение в интервале [ -200; 400] (400 включительно):
public class Test { public static void main(String[] args){ int a = (int) (Math.random()*(600+1)) – 200; System.out.println(a); } } |
Пример №9
Целочисленное значение в интервале [ 1; 2] (2 включительно):
public class Test { public static void main(String[] args){ int a = (int) (Math.random()*(1+1)) + 1; System.out.println(a); } } |
Надеемся, что наша статья была Вам полезна. Также есть возможность записаться на наши курсы по Java в Киеве. Обучаем с нуля. Детальную информацию Вы можете найти у нас на сайте.
Афоризм
Вы с этим умным видом даже спите?
Наталья Резник
Поддержка проекта
Если Вам сайт понравился и помог, то будем признательны за Ваш «посильный» вклад в его поддержку и развитие
• Yandex.Деньги
410013796724260
• Webmoney
R335386147728
Z369087728698
Генерация случайных чисел
Класс Math библиотеки Java имеет метод random(), который генерирует случайное значение в диапазоне
[0,1). Обратите внимание, что данный диапазон не включает 1 и при описании закрывается круглой скобкой. Можно ли
предсказать сгенерированное значение? Теоретически возможно, но практически – это очень труднореализуемая задача.
А поскольку существует небольшая вероятность предсказывания случайно-сгенерируемого значения, то такие числа принято
называть не случайными, а псевдослучайными.
Чтобы получить псевдо-случайное число в определенном диапазоне необходимо значение метода random() умножить
на величину диапазона значений. Например, необходимо генерировать значение в диапазоне от min до max. В этом случае
можно использовать следующий код :
double d = Math.random() * (max - min) + min;
Допустим, что необходимо получить значение в диапазоне [1,10), где min=1, max=10 (10 исключительно)
.
Алгоритм работает следующим образом : диапазон [0;1) умножается на 9=(10-1), соответственно получаем :
- нижняя граница: 0*9 = 0;
- верхняя граница: 1*9 = 9,
получаем диапазон [0,9), к которому добавляем min=1. В результате имеем :
- нижняя граница: 0 + 1 = 1;
- верхняя граница: 9 + 1 = 10.
После подстановки значений в выражение, получим :
double d = Math.random() * (10 - 1) + 1;
Диапазон [-10, 10)
Чтобы получить псевдослучайное число в диапазоне от -10 до 10 (исключительно), необходимо значение
Math.random() умножить на 20 и вычесть 10, как это представлено в следующем примере :
// после подстановки значений double d = Math.random() * (10 - (-10)) + (-10); // получаем double d = Math.random() * 20 - 10;
Генерирование целочисленных псевдослучайных значений
Для генерирования целочисленных псевдослучайных значений используется представленное выше выражение, в котором
произведение «приводится» к целочисленному значению. Например, попробуем получить псевдослучайное значение в диапазоне
[5,20]. Обратите внимание, что закрывающаяся скобка квадратная, т.е. 20 входит в диапазон. В этом случае к разности
между максимальным и минимальным значениями следует добавить 1, т.е. определить диапазон целочисленных значений [5,21),
где 21 не попадает в желаемый диапазон :
// после подстановки значений int i = (int)Math.random() * (20 - 5 + 1) + 5; // получаем int i = (int)Math.random() * 16 + 5;
Класс Random
В качестве генератора псевдослучайных чисел можно также использовать класс java.util.Random, имеющий два
конструктора :
public Random(); public Random(long);
Поскольку Random создаёт псевдослучайное число, то определив начальное число, устанавливается начальная точка
случайной последовательности, способствующая получению одинаковых случайных последовательностей. Чтобы избежать такого
совпадения, обычно применяют второй конструктор с использованием в качестве инициирующего значения текущего времени.
В таблице представлены наиболее часто используемые методы генератора Random :
Метод | Описание |
---|---|
boolean nextBoolean() | получение следующего случайного значения типа boolean |
double nextDouble() | получение следующего случайного значения типа double |
float nextFloat() | получение следующего случайного значения типа float |
int nextInt() | получение следующего случайного значения типа int |
int nextInt(int n) | получение следующего случайного значения типа int в диапазоне от 0 до n |
long nextLong() | получение следующего случайного значения типа long |
void nextBytes(byte[] buf) | формирование массива из случайно генерируемых значений |
Пример получения псевдослучайного целочисленного значения с использованием класса Random :
Random random = new Random(); int i = random.nextInt();
С классом Random алгоритм получения псевдослучайного числа такой же, как и у метода random класса
Math. Допустим, что нам необходимо получить случайное число в диапазоне [5,100], 100 включительно. В этом случае
код может выглядеть следующим образом :
int min = 5; int max = 100; int diff = max - min; Random random = new Random(); int i = random.nextInt(diff + 1) + min;
Класс SecureRandom
Для криптографии следует применять класс
SecureRandom, использующий криптографически сильный генератор случайных чисел (random number
generator RNG).
В следующем примере формируется массив псевдослучайных значений типа byte :
SecureRandom random = new SecureRandom(); byte bytes[] = new byte[8]; random.nextBytes(bytes);
Этот же массив можно сформировать методом generateSeed :
byte seed[] = random.generateSeed(8);
Пример использования SecureRandom представлен на странице
Симметричного шифрования.
Класс ThreadLocalRandom
В JDK 7 включен класс ThreadLocalRandom из многопоточного пакета
java.util.concurrent, который следует использовать для получения псевдослучайных
значений в многопоточных приложениях. Для получения экземпляра ThreadLocalRandom следует использовать
статический метод current() данного класса. Пример :
ThreadLocalRandom random = ThreadLocalRandom.current(); System.out.println("Random values : "); System.out.println("boolean : " + random.nextBoolean()); System.out.println("int : " + random.nextInt ()); System.out.println("float : " + random.nextFloat ()); System.out.println("long : " + random.nextLong ()); System.out.println("int from 0 to 5 : " + random.nextInt(5)); System.out.println("long from 5 to 15 : " + random.nextLong(5, 15));
Вступление
В этом руководстве мы рассмотрим, как сгенерировать случайные целые
числа в определенном диапазоне в Java .
Мы рассмотрим несколько подходов, включая базовую Java и сторонние
решения:
- Random.ints ()
- Random.nextInt ()
- Math.random ()
- SecureRandom.nextInt ()
- ThreadLocalRandom.nextInt ()
- SplittableRandom.ints ()
Примечание. Для каждого подхода мы рассмотрим, как сгенерировать
одно случайное целое число, а также как сгенерировать
последовательность случайных целых чисел .
Все эти методы включают нижнюю границу и исключают верхнюю границу .
Random.ints ()
Мы начали с Random.ints()
который был добавлен в Random
в Java 8
именно для этой цели. Изначально в Java не было полностью интуитивно
понятного , встроенного решения этой задачи.
Метод ints()
возвращает последовательность случайных значений в форме
IntStream
. Будучи Stream
, она неограниченна:
Random random = new Random();
random.ints().forEach(System.out::println);
Это приводит к:
-526320702
-744603161
474879020
1864311422
406782252
...
Это неограниченный IntStream
, который будет генерировать любое
значение от Integer.MIN_VALUE
до Integer.MAX_VALUE
. Однако вы
можете указать диапазон , а также количество элементов, которые вы
хотите создать.
Кроме того, первый аргумент – это количество элементов, которые вы
хотите сгенерировать – в противном случае поток будет генерировать
неограниченное количество элементов, пока не закончится ваше
пространство кучи:
List<Integer> intList = new Random().ints(5, 1, 11)
.boxed()
.collect(Collectors.toList());
System.out.println(intList);
Перед сбором IntStream
нам придется упаковать его с помощью boxed()
, который возвращает поток, состоящий из элементов IntStream
,
упакованных в Integer
. Затем мы запускаем collect()
в возвращенном
потоке, а не в исходном.
Метод collect()
объекта IntStream
не возвращает коллекцию – он
выполняет изменяемую операцию
сокращения
.
Выполнение этого кода приводит к:
[1, 9, 9, 6, 2]
Чтобы сгенерировать одно случайное целое число, вы можете просто
настроить первый аргумент метода ints()
или использовать findFirst()
и getAsInt()
чтобы извлечь его из IntStream
:
int randomInt = new Random().ints(1, 1, 11).findFirst().getAsInt();
System.out.println(randomInt);
Это приводит к случайному целому числу в диапазоне от 1..10
(второго
аргумента является исключительным):
5
Random.nextInt ()
Более классический пример, который вы часто будете видеть, – это просто
использование Random.nextInt()
. Он принимает bound
, который
устанавливает верхнюю границу , а по умолчанию устанавливает нижнюю
границу равной 0
К сожалению, это не позволяет вам изменить это, поэтому можно
использовать быстрый и простой «взлом», чтобы указать границы:
int min = 10;
int max = 100;
System.out.println(new Random().nextInt(max - min) + min);
Это приводит к случайному целому числу в диапазоне от min
до max
:
53
Для генерации такой последовательности нам потребуется вызвать метод
несколько раз:
public static List<Integer> intsInRange(int size, int lowerBound, int upperBound) {
Random random = new Random();
List<Integer> result = new ArrayList<>();
for (int i = 0; i < size; i++) {
result.add(random.nextInt(upperBound - lowerBound) + lowerBound);
}
return result;
}
Это ограниченное List
воссоздание функции Random.ints()
, которая
просто возвращает список случайно сгенерированных целых чисел в
диапазоне с заданным размером:
List<Integer> integerList = intsInRange(5, 0, 10);
System.out.println(integerList);
Запуск этого кода приведет к чему-то вроде:
[3, 8, 2, 2, 9]
SecureRandom.nextInt ()
Класс SecureRandom
является альтернативой классическому Random
, но
предоставляет криптографически стойкий генератор случайных чисел.
Random
изнутри полагается на системные часы для генерации начальных
чисел, что не является на самом деле случайным.
С другой стороны, SecureRandom
берет гораздо больше случайных данных
из среды, чтобы сгенерировать гораздо более случайное начальное число.
Если вас беспокоит криптографическая безопасность, вы можете
SecureRandom
который ведет себя почти так же, как Random
с точки
зрения разработчика:
int max = 100;
int min = 10;
int randomInt = new SecureRandom().nextInt(max - min) + min;
System.out.println(randomInt);
В результате получается случайное целое число в диапазоне от min
до
max
:
95
А если вы хотите сгенерировать последовательности, можно создать
вспомогательный метод:
public static List<Integer> intsInRange(int size, int lowerBound, int upperBound) {
SecureRandom random = new SecureRandom();
List<Integer> result = new ArrayList<>();
for (int i = 0; i < size; i++) {
result.add(random.nextInt(upperBound - lowerBound) + lowerBound);
}
return result;
}
Что вы можете использовать как:
List<Integer> integerList = intsInRange3(5, 0, 10);
System.out.println(integerList);
И в результате:
[0, 9, 5, 6, 5]
Math.random ()
Класс Math
предоставляет нам отличные вспомогательные методы,
связанные с математикой. Одним из них является Math.random()
метод,
который возвращает случайное значение между 0..1
. Обычно он
используется для генерации случайных значений процентилей.
Однако, аналогично Random.nextInt()
– вы можете использовать эту
функциональность для генерации любого целого числа в определенном
диапазоне:
int min = 10;
int max = 100;
int randomNumber = (int)(Math.random() * (max + 1 - min) + min);
System.out.println(randomNumber);
Хотя этот подход еще менее интуитивно понятен, чем предыдущий.
Выполнение этого кода приводит к чему-то вроде:
43
Если вы хотите работать с последовательностью, мы бы создали
вспомогательный метод для добавления каждого сгенерированного значения в
список:
public static List<Integer> intsInRange(int size, int lowerBound, int upperBound) {
List<Integer> result = new ArrayList<>();
for (int i = 0; i < size; i++) {
result.add((int)(Math.random() * (upperBound + 1 - lowerBound) + lowerBound));
}
return result;
}
И тогда мы можем назвать это так:
List<Integer> integerList = intsInRange(5, 0, 10);
System.out.println(integerList);
Что производит:
[9, 0, 3, 2, 0]
ThreadLocalRandom.nextInt ()
Если вы работаете в многопоточной среде, ThreadLocalRandom
предназначен для использования в качестве поточно-безопасного
эквивалента Random
. К счастью, он предлагает nextInt()
метод
как с верхней и нижней границы:
int randomInt = ThreadLocalRandom.current().nextInt(0, 10);
System.out.println(randomInt);
Как обычно, нижняя граница включена, а верхняя – нет:
3
Точно так же вы можете создать вспомогательную функцию для генерации их
последовательности:
public static List<Integer> intsInRange(int size, int lowerBound, int upperBound) {
List<Integer> result = new ArrayList<>();
for (int i = 0; i < size; i++) {
result.add(ThreadLocalRandom.current().nextInt(lowerBound, upperBound));
}
return result;
}
Что вы можете использовать как:
List<Integer> integerList = intsInRange4(5, 0, 10);
System.out.println(integerList);
[1, 9, 1, 9, 7]
SplittableRandom.ints ()
Менее известным классом в Java API является SplittableRandom
который
используется в качестве генератора псевдослучайных значений. Как следует
из названия, он разделяется и работает параллельно, и на самом деле
используется только тогда, когда у вас есть задачи, которые можно снова
разделить на более мелкие подзадачи.
Стоит отметить, что этот класс также основан на незащищенной генерации
семян – если вы ищете безопасную генерацию семян, используйте
SecureRandom
.
Класс предлагает ints()
, который, с нашей точки зрения, работает так
же, как Random.ints()
:
List<Integer> intList = new SplittableRandom().ints(5, 1, 11)
.boxed()
.collect(Collectors.toList());
System.out.println(intList);
Что приводит к:
[3, 2, 8, 10, 3]
И, если вы хотите сгенерировать только одно случайное число, вы можете
отказаться от сборщика и использовать findFirst()
с getAsInt()
:
int randomInt = new SplittableRandom().ints(1, 1, 11).findFirst().getAsInt();
System.out.println(randomInt);
Что приводит к:
4
Заключение
В этом руководстве мы подробно рассмотрели, как генерировать случайные
целые числа в диапазоне в Java .
Мы рассмотрели самый новый и самый полезный метод, а также некоторые
другие популярные методы завершения этой задачи. Большинство подходов
основаны на Random
или Random
эквивалентных, используемых для более
конкретных контекстов.