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

Я пытаюсь создать случайное значение int с Java, но в определенном диапазоне.

Например:

Мой диапазон 5 - 10, что означает, что 5 - наименьшее возможное значение, а 10 - это самый большой. Любое другое число между этими числами также может быть значением.

В Java существует метод random() в классе Math, который возвращает значение double между 0.0 и 1.0. В классе Random существует метод nextInt(int n), который возвращает случайное значение int в диапазоне 0 (включительно) и n (исключение). Я не смог найти метод, который возвращает случайное целочисленное значение между двумя числами.

Я пробовал следующие вещи, но у меня все еще есть проблемы: (минимальные и максимальные - наименьшие и самые большие).

Решение 1:

randomNum = minimum + (int)(Math.random() * maximum); 

Проблема:

randomNum может быть больше maximum.

Решение 2:

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

Проблема:

randomNum может быть меньше minimum.

Как решить эти проблемы?

Я также пробовал просматривать архив и нашел:

Но я не мог решить проблему.

2617
задан user42155 12 дек. '08 в 21:20
источник поделиться

53 ответов

  • 1
  • 2

В 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, который может быть источником путаницы и ошибки при неправильном использовании.

Однако, наоборот, нет возможности явно установить семя, поэтому может быть трудно воспроизвести результаты в ситуациях, когда это полезно, например, при тестировании или сохранении игровых состояний или аналогичных. В этих ситуациях можно использовать метод до 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 not get 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 в стандартной библиотеке.

2920
ответ дан Greg Case 12 дек. '08 в 21:25
источник поделиться

Обратите внимание, что этот подход более предвзятый и менее эффективный, чем подход nextInt, qaru.site/questions/1788/...

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

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

Java Функция математической библиотеки 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))
1278
ответ дан TJ_Fischer 12 дек. '08 в 21:35
источник поделиться

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

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

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

273
ответ дан jackson 04 сент. '09 в 7:23
источник поделиться

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

minimum + rn.nextInt(maxValue - minvalue + 1)
108
ответ дан krosenvold 12 дек. '08 в 21:25
источник поделиться

Вы можете отредактировать свой второй пример кода, чтобы:

Random rn = new Random();
int range = maximum - minimum + 1;
int randomNum =  rn.nextInt(range) + minimum;
80
ответ дан Bill the Lizard 12 дек. '08 в 21:31
источник поделиться

С они внедрили метод 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.

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

80
ответ дан Alexis C. 26 нояб. '14 в 21:29
источник поделиться

Достаточно небольшой модификации вашего первого решения.

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

Подробнее о реализации класса Random: Random

70
ответ дан hexabunny 13 марта '15 в 1:44
источник поделиться

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

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

x, y - интервалы, например. (1,10)

47
ответ дан andrew 13 февр. '13 в 2:19
источник поделиться

Класс Math.Random в Java основан на 0. Итак, если вы пишете что-то вроде

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

x будет находиться между 0-9 включительно.

Итак, учитывая следующий массив из 25 элементов, код для генерации случайного числа между 0 (база массива) и array.length будет:

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

index = rand.nextInt(i.Length)

Так как i.Length вернет 25, nextInt(i.Length) вернет число между диапазоном 0-24. Другой вариант идет с Math.Random, который работает одинаково.

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

Для лучшего понимания ознакомьтесь с сообщением форума Random Intervals (archive.org).

46
ответ дан Matt R 08 янв. '09 в 18:04
источник поделиться

Простите меня за брезгливость, но решение, предложенное большинством, т.е. min + rng.nextInt(max - min + 1)), кажется опасным из-за того, что:

  • rng.nextInt(n) не может достичь Integer.MAX_VALUE.
  • (max - min) может вызвать переполнение, когда min отрицательный.

Безопасное решение вернет правильные результаты для любого min <= max внутри [Integer.MIN_VALUE, Integer.MAX_VALUE]. Рассмотрим следующую наивную реализацию:

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;
}

Несмотря на неэффективность, обратите внимание, что вероятность успеха в цикле while всегда будет 50% или выше.

36
ответ дан Joel Sjöstrand 10 янв. '11 в 16:19
источник поделиться

Интересно, подходит ли какой-либо метод генерации случайных чисел, предоставленный библиотекой Apache Commons Math.

Например: RandomDataGenerator.nextInt или RandomDataGenerator.nextLong

18
ответ дан Chinnery 12 дек. '08 в 21:27
источник поделиться

Возьмем пример.

Предположим, что я хочу сгенерировать число между 5-10.

    int max=10;
    int min=5;
    int diff=max-min;
    Random rn = new Random();
    int i = rn.nextInt(diff+1);
    i+=min;
    System.out.print("The Random Number is " + i);

Давайте поймем это...

Инициализировать max с наивысшим значением и минимальным значением.

     

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

     
  

5, 6, 7, 8, 9, 10

  
  

Таким образом, подсчет этого будет max-min + 1.

     
  

то есть. 10-5 + 1 = 6

  
  

Случайное число будет генерировать число между 0-5.

     
  

то есть. 0, 1, 2, 3, 4, 5

  
  

Добавление значения min к случайному числу приведет к созданию

     
  

5, 6, 7, 8, 9, 10

  
  

Отсюда получаем требуемый диапазон.

17
ответ дан Sunil Chawla 03 авг. '14 в 6:07
источник поделиться

Создайте случайное число для разности min и max с помощью метода nextint (n), а затем добавьте минимальное число в результат:

Random rn = new Random();
int result = rn.nextInt(max - min + 1) + min;
System.out.println(result);
16
ответ дан gifpif 27 мая '15 в 13:43
источник поделиться

Здесь полезный класс для генерации случайных ints в диапазоне с любой комбинацией включительно/исключительных границ:

import java.util.Random;

public class RandomRange extends Random {
    public int nextIncInc(int min, int max) {
        return nextInt(max - min + 1) + min;
    }

    public int nextExcInc(int min, int max) {
        return nextInt(max - min) + 1 + min;
    }

    public int nextExcExc(int min, int max) {
        return nextInt(max - min - 1) + 1 + min;
    }

    public int nextIncExc(int min, int max) {
        return nextInt(max - min) + min;
    }
}
15
ответ дан Garrett Hall 15 февр. '12 в 19:19
источник поделиться

Эти методы могут быть удобны в использовании:

Этот метод возвращает случайное число между предоставленным минимальным и максимальным значением:

public static int getRandomNumberBetween(int min, int max) {
        Random foo = new Random();
        int randomNumber = foo.nextInt(max - min) + min;
        if(randomNumber == min) {
            // Since the random number is between the min and max values, simply add 1
            return min + 1;
        }
        else {
            return randomNumber;
        }

    }

и этот метод вернет случайное число из предоставленное минимальное и максимальное значение (поэтому сгенерированное число также может быть минимальным или максимальным числом):

public static int getRandomNumberFrom(int min, int max) {
        Random foo = new Random();
        int randomNumber = foo.nextInt((max + 1) - min) + min;

        return randomNumber;

    }
13
ответ дан Luke Taylor 12 авг. '12 в 18:01
источник поделиться

В случае прокатки кости это будет случайное число от 1 до 6 (не от 0 до 6), поэтому:

face = 1 + randomNumbers.nextInt(6);
13
ответ дан sam 16 февр. '10 в 11:50
источник поделиться

Try

rand.nextInt((max+1) - min) + min;
13
ответ дан Michael Myers 12 дек. '08 в 21:25
источник поделиться

Вот простой пример, который показывает, как генерировать случайное число из замкнутого диапазона [min, max], а min <= max is true

Вы можете использовать его как поле в классе дыр, также имея все методы Random.class в одном месте

Пример результатов:

RandomUtils random = new RandomUtils();
random.nextInt(0, 0); // returns 0
random.nextInt(10, 10); // returns 10
random.nextInt(-10, 10); // returns numbers from -10 to 10 (-10, -9....9, 10)
random.nextInt(10, -10); // throws assert

Источники:

import junit.framework.Assert;
import java.util.Random;

public class RandomUtils extends Random {

    /**
     * @param min generated value. Can't be > then max
     * @param max generated value
     * @return values in closed range [min, max].
     */
    public int nextInt(int min, int max) {
        Assert.assertFalse("min can't be > then max; values:[" + min + ", " + max + "]", min > max);
        if (min == max) {
            return max;
        }

        return nextInt(max - min + 1) + min;
    }
}
12
ответ дан Yakiv Mospan 28 нояб. '14 в 3:50
источник поделиться
public static Random RANDOM = new Random(System.nanoTime());

public static final float random(final float pMin, final float pMax) {
    return pMin + RANDOM.nextFloat() * (pMax - pMin);
}
12
ответ дан AZ_ 13 июля '11 в 14:31
источник поделиться

Просто используйте класс Random:

Random ran = new Random();
// Assumes max and min are non-negative.
int randomInt = min + ran.nextInt(max - min + 1);
11
ответ дан Prof Mo 24 дек. '13 в 16:33
источник поделиться
int random = minimum + Double.valueOf(Math.random()*(maximum-minimun)).intValue();

Или взгляните на RandomUtils из Apache Commons.

11
ответ дан user2427 12 дек. '08 в 21:28
источник поделиться

Когда вам нужно много случайных чисел, я не рекомендую класс Random в API. У этого есть только слишком маленький период. Вместо этого попробуйте Mersenne twister. Существует реализация Java.

10
ответ дан raupach 13 дек. '08 в 13:18
источник поделиться

Я нашел этот пример на http://www.javapractices.com/topic/TopicAction.do?Id=62:


В этом примере генерируются случайные целые числа в определенном диапазоне.

import java.util.Random;

/** Generate random integers in a certain range. */
public final class RandomRange {

  public static final void main(String... aArgs){
    log("Generating random integers in the range 1..10.");

    int START = 1;
    int END = 10;
    Random random = new Random();
    for (int idx = 1; idx <= 10; ++idx){
      showRandomInteger(START, END, random);
    }

    log("Done.");
  }

  private static void showRandomInteger(int aStart, int aEnd, Random aRandom){
    if ( aStart > aEnd ) {
      throw new IllegalArgumentException("Start cannot exceed End.");
    }
    //get the range, casting to long to avoid overflow problems
    long range = (long)aEnd - (long)aStart + 1;
    // compute a fraction of the range, 0 <= frac < range
    long fraction = (long)(range * aRandom.nextDouble());
    int randomNumber =  (int)(fraction + aStart);    
    log("Generated : " + randomNumber);
  }

  private static void log(String aMessage){
    System.out.println(aMessage);
  }
} 

Пример запуска этого класса:

Generating random integers in the range 1..10.
Generated : 9
Generated : 3
Generated : 3
Generated : 9
Generated : 4
Generated : 1
Generated : 3
Generated : 9
Generated : 10
Generated : 10
Done.
10
ответ дан Hospes 07 июня '12 в 13:38
источник поделиться

Вы можете добиться этого в Java 8.

    Random random = new Random();

    int max = 10;
    int min = 5;
    int totalNumber = 10;

    IntStream stream = random.ints(totalNumber, min, max);
    stream.forEach(System.out::println);
9
ответ дан Mulalo Madida 20 июня '17 в 15:39
источник поделиться

Другим вариантом является использование Apache Commons:

import org.apache.commons.math.random.RandomData;
import org.apache.commons.math.random.RandomDataImpl;

public void method( ) {
    RandomData randomData = new RandomDataImpl( );
    int number = randomData.nextInt(5,10);
9
ответ дан gerardw 18 янв. '12 в 19:15
источник поделиться

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

public class Randomizer
{
    public static int generate(int min,int max)
    {
        return min + (int)(Math.random() * ((max - min) + 1));
    }

    public static void main(String[] args)
    {
        System.out.println(Randomizer.generate(0,10));
    }
}

Это просто чисто и просто.

9
ответ дан Abel Melquiades Callejo 01 сент. '13 в 5:53
источник поделиться

Лучше использовать SecureRandom, а не просто Random.

public static int generateRandomInteger(int min, int max) {
    SecureRandom rand = new SecureRandom();
    rand.setSeed(new Date().getTime());
    int randomNum = rand.nextInt((max - min) + 1) + min;
    return randomNum;
}
9
ответ дан grep 26 марта '15 в 16:02
источник поделиться
private static Random random = new Random();    

public static int getRandomInt(int min, int max){
  return random.nextInt(max - min + 1) + min;
}

ИЛИ

public static int getRandomInt(Random random, int min, int max)
{
  return random.nextInt(max - min + 1) + min;
}
8
ответ дан Muhammad Aamir Talib 11 февр. '15 в 14:40
источник поделиться
import java.util.Random; 

public class RandomUtil {
    // Declare as class variable so that it is not re-seeded every call
    private static Random random = new Random();

    /**
     * Returns a psuedo-random number between min and max (both inclusive)
     * @param min Minimim value
     * @param max Maximim value. Must be greater than min.
     * @return Integer between min and max (both inclusive)
     * @see java.util.Random#nextInt(int)
     */
    public static int nextInt(int min, int max) {
        // nextInt is normally exclusive of the top value,
        // so add 1 to make it inclusive
        return random.nextInt((max - min) + 1) + min;
    }
}
7
ответ дан user1734143 14 июня '14 в 6:50
источник поделиться
rand.nextInt((max+1) - min) + min;

Это прекрасно работает.

7
ответ дан ganesh 22 февр. '10 в 14:44
источник поделиться
  • 1
  • 2

Другие вопросы по меткам