Вопрос: Как генерировать случайные целые числа в определенном диапазоне в Java?


Как создать случайную intзначение в определенном диапазоне?

Я пробовал следующее, но это не работает:

Попытка 1:

randomNum = minimum + (int)(Math.random() * maximum);
// Bug: `randomNum` can be bigger than `maximum`.

Попытка 2:

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;
// Bug: `randomNum` can be smaller than `minimum`.

2857


источник


Ответы:


В Java 1.7 или новее , стандартный способ сделать это следующим образом:

import java.util.concurrent.ThreadLocalRandom;

// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);

Видеть соответствующий JavaDoc , Преимущество такого подхода состоит в том, что не нужно явно инициализировать java.util.Random экземпляр, который может быть источником путаницы и ошибки при неправильном использовании.

Однако, наоборот, нет возможности явно установить семя, поэтому может быть трудно воспроизвести результаты в ситуациях, когда это полезно, например, при тестировании или сохранении игровых состояний или аналогичных. В таких ситуациях может использоваться метод pre-Java 1.7, показанный ниже.

Перед Java 1.7 , стандартный способ сделать это следующим образом:

import java.util.Random;

/**
 * Returns a pseudo-random number between min and max, inclusive.
 * The difference between min and max can be at most
 * <code>Integer.MAX_VALUE - 1</code>.
 *
 * @param min Minimum value
 * @param max Maximum value.  Must be greater than min.
 * @return Integer between min and max, inclusive.
 * @see java.util.Random#nextInt(int)
 */
public static int randInt(int min, int max) {

    // NOTE: This will (intentionally) not run as written so that folks
    // copy-pasting have to think about how to initialize their
    // Random instance.  Initialization of the Random instance is outside
    // the main scope of the question, but some decent options are to have
    // a field that is initialized once and then re-used as needed or to
    // use ThreadLocalRandom (if using at least Java 1.7).
    // 
    // In particular, do NOT do 'Random rand = new Random()' here or you
    // will get not very good / not very random results.
    Random rand;

    // nextInt is normally exclusive of the top value,
    // so add 1 to make it inclusive
    int randomNum = rand.nextInt((max - min) + 1) + min;

    return randomNum;
}

Видеть соответствующий JavaDoc , На практике java.util.Random класс часто предпочтительнее java.lang.Math.random () ,

В частности, нет необходимости повторно изобретать колесо генерации случайных целых чисел, когда для выполнения задачи имеется простой API в стандартной библиотеке.


3197



Обратите внимание, что этот подход более предвзятый и менее эффективный, чем nextIntподход, https://stackoverflow.com/a/738651/360211

Один стандартный шаблон для этого:

Min + (int)(Math.random() * ((Max - Min) + 1))

Ява Функция математической библиотеки Math.random () генерирует двойное значение в диапазоне [0,1), Обратите внимание, что этот диапазон не включает 1.

Чтобы сначала получить определенный диапазон значений, вам нужно умножить на величину диапазона значений, которые вы хотите покрыть.

Math.random() * ( Max - Min )

Это возвращает значение в диапазоне [0,Max-Min), где «Макс-Мин» не включен.

Например, если вы хотите [5,10], вам нужно покрыть пять целых значений, чтобы вы использовали

Math.random() * 5

Это вернет значение в диапазоне [0,5), где 5 не входит.

Теперь вам нужно сдвинуть этот диапазон до диапазона, на который вы нацеливаетесь. Вы делаете это, добавляя значение Min.

Min + (Math.random() * (Max - Min))

Теперь вы получите значение в диапазоне [Min,Max), Следуя нашему примеру, это означает [5,10):

5 + (Math.random() * (10 - 5))

Но это все еще не включает Maxи вы получаете двойное значение. Чтобы получить Maxзначение включено, вам нужно добавить 1 к вашему параметру диапазона (Max - Min)а затем усечь десятичную часть путем литья в int. Это достигается посредством:

Min + (int)(Math.random() * ((Max - Min) + 1))

И вот он у вас есть. Случайное целочисленное значение в диапазоне [Min,Max], или на пример [5,10]:

5 + (int)(Math.random() * ((10 - 5) + 1))

1315



Использование:

Random ran = new Random();
int x = ran.nextInt(6) + 5;

Целое число xтеперь является случайным числом, которое имеет возможный результат 5-10,


309



Использование:

minimum + rn.nextInt(maxValue - minvalue + 1)

120



С они ввели метод ints(int randomNumberOrigin, int randomNumberBound)в Randomкласс.

Например, если вы хотите сгенерировать пять случайных целых чисел (или один) в диапазоне [0, 10], просто выполните:

Random r = new Random();
int[] fiveRandomNumbers = r.ints(5, 0, 11).toArray();
int randomNumber = r.ints(1, 0, 11).findFirst().getAsInt();

Первый параметр указывает только размер IntStream(который является перегруженным методом того, который создает неограниченный IntStream).

Если вам нужно выполнить несколько отдельных вызовов, вы можете создать бесконечный примитивный итератор из потока:

public final class IntRandomNumberGenerator {

    private PrimitiveIterator.OfInt randomIterator;

    /**
     * Initialize a new random number generator that generates
     * random numbers in the range [min, max]
     * @param min - the min value (inclusive)
     * @param max - the max value (inclusive)
     */
    public IntRandomNumberGenerator(int min, int max) {
        randomIterator = new Random().ints(min, max + 1).iterator();
    }

    /**
     * Returns a random number in the range (min, max)
     * @return a random number in the range (min, max)
     */
    public int nextInt() {
        return randomIterator.nextInt();
    }
}

Вы также можете сделать это для doubleа также longзначения.

Надеюсь, поможет! :)


96



You can edit your second code example to:

Random rn = new Random();
int range = maximum - minimum + 1;
int randomNum =  rn.nextInt(range) + minimum;

90



Just a small modification of your first solution would suffice.

Random rand = new Random();
randomNum = minimum + rand.nextInt((maximum - minimum) + 1);

See more here for implementation of Random


84



ThreadLocalRandom equivalent of class java.util.Random for multithreaded environment. Generating a random number is carried out locally in each of the threads. So we have a better performance by reducing the conflicts.

int rand = ThreadLocalRandom.current().nextInt(x,y);

x,y - intervals e.g. (1,10)


53



The Math.Random class in Java is 0-based. So, if you write something like this:

Random rand = new Random();
int x = rand.nextInt(10);

x will be between 0-9 inclusive.

So, given the following array of 25 items, the code to generate a random number between 0 (the base of the array) and array.length would be:

String[] i = new String[25];
Random rand = new Random();
int index = 0;

index = rand.nextInt( i.length );

Since i.length will return 25, the nextInt( i.length ) will return a number between the range of 0-24. The other option is going with Math.Random which works in the same way.

index = (int) Math.floor(Math.random() * i.length);

For a better understanding, check out forum post Random Intervals (archive.org).


51



Forgive me for being fastidious, but the solution suggested by the majority, i.e., min + rng.nextInt(max - min + 1)), seems perilous due to the fact that:

  • rng.nextInt(n) cannot reach Integer.MAX_VALUE.
  • (max - min) may cause overflow when min is negative.

A foolproof solution would return correct results for any min <= max within [Integer.MIN_VALUE, Integer.MAX_VALUE]. Consider the following naive implementation:

int nextIntInRange(int min, int max, Random rng) {
   if (min > max) {
      throw new IllegalArgumentException("Cannot draw random int from invalid range [" + min + ", " + max + "].");
   }
   int diff = max - min;
   if (diff >= 0 && diff != Integer.MAX_VALUE) {
      return (min + rng.nextInt(diff + 1));
   }
   int i;
   do {
      i = rng.nextInt();
   } while (i < min || i > max);
   return i;
}

Although inefficient, note that the probability of success in the while loop will always be 50% or higher.


41



I wonder if any of the random number generating methods provided by an Apache Commons Math library would fit the bill.

For example: RandomDataGenerator.nextInt or RandomDataGenerator.nextLong


23



 rand.nextInt((max+1) - min) + min;

20