Как генерировать случайные целые числа в определенном диапазоне в 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`.
12.12.2008 18:20:57
Прежде чем опубликовать новый ответ, учтите, что на этот вопрос уже есть более 65 ответов. Пожалуйста, убедитесь, что ваш ответ содержит информацию, которой нет среди существующих ответов.
janniks 3.02.2020 11:53:35
30 ОТВЕТОВ

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

minimum + rn.nextInt(maxValue - minvalue + 1)
156
22.06.2014 22:22:52

В 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 для выполнения задачи.

3766
14.10.2018 17:08:35
Для вызовов, для которых maxзначение равно, Integer.MAX_VALUEвозможно переполнение, что приводит к java.lang.IllegalArgumentException. Вы можете попробовать: randInt(0, Integer.MAX_VALUE). Кроме того, если nextInt((max-min) + 1)возвращает самое высокое значение (я полагаю, довольно редко), оно не переполнится снова (предположим, что min и max - достаточно высокие значения)? Как бороться с такими ситуациями?
Daniel 12.08.2014 10:34:30
@MoisheLipsker Должно быть, что nextLong не берет ограничение, как nextInteger
mmm 17.06.2015 18:42:57
@leventov ThreadLocalRandomбыл добавлен в Java через 2 1/2 года после того, как этот вопрос был впервые задан. Я всегда твердо придерживался мнения, что управление экземпляром Random находится за рамками вопроса.
Greg Case 11.09.2015 01:57:18
В Android Random rand = new Random ();
Webserveis 3.10.2016 19:55:05
@Webserveis Это рассматривается в комментариях к примеру. Короткая версия - вы не должны = new Random () для каждого вызова функции, иначе ваши результаты не будут достаточно случайными во многих случаях.
Greg Case 4.10.2016 00:29:17
 rand.nextInt((max+1) - min) + min;
27
20.12.2017 19:34:30

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

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

32
16.11.2016 12:08:17
int random = minimum + Double.valueOf(Math.random()*(maximum-minimum )).intValue();

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

18
8.02.2019 14:11:23
Это полезно, но остерегайтесь небольшого недостатка: сигнатуры методов выглядят следующим образом: nextDouble (double startInclusive, double endInclusive), но если вы загляните внутрь методов, endInclusive на самом деле должно быть endExclusive.
zakmck 30.01.2015 09:27:17
Double.valueOf(Math.random()*(maximum-minimun)).intValue()это довольно запутанный (и неэффективный) способ сказать (int)(Math.random()*(maximum-minimun))
Holger 3.06.2016 09:47:15
Несоответствие орфографии для минимального минимума возврата + Double.valueOf (Math.random () * (максимум - минимум)). IntValue ();
Hrishikesh Mishra 26.12.2016 05:14:23

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

Random rn = new Random();
int range = maximum - minimum + 1;
int randomNum =  rn.nextInt(range) + minimum;
103
8.02.2019 13:02:02

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

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

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

Функция библиотеки Java Math 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))
1412
8.02.2019 14:13:34
В документации Sun явно сказано, что вам лучше использовать Random (), если вам нужно int вместо Math.random (), который выдает double.
Lilian A. Moraru 23.02.2012 23:26:34
Это на самом деле предвзято по сравнению с методами nextInt stackoverflow.com/a/738651/360211
weston 29.12.2016 13:35:53
«Предвзятый» в данном случае означает, что после 2 ^ 53 казней у некоторых чисел будет в среднем один дополнительный случай.
Cephalopod 29.08.2019 09:48:18

Когда вам нужно много случайных чисел, я не рекомендую случайный класс в API. У него слишком маленький период. Попробуйте вместо этого твистер Мерсенна . Есть реализация Java .

16
1.08.2013 18:02:34

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

Для лучшего понимания, проверьте сообщение на форуме Случайные интервалы (archive.org) .

66
8.02.2019 14:14:25
+1 для ссылки скриншота архива wayBackMachine, и ваш ответ по-прежнему полезен для получения "случайных" целых чисел в диапазоне.
Tapper7 30.10.2016 05:44:57
Это
AjahnCharles 2.08.2017 13:53:53
@CodeConfident indexПеременная не повлияет на результат случайного числа. Вы можете инициализировать его любым удобным для вас способом, не беспокоясь об изменении результата. Надеюсь это поможет.
Matt R 2.08.2017 14:38:52
Точно ... это совершенно не используется. Я бы инициализировал его прямо к рэнду:int index = rand.nextInt(i.Length);
AjahnCharles 2.08.2017 14:41:09
Или нет совсем. int index; \n index = rand...если кто-то увлекается объявлениями и присваиваниями в разных строках. Некоторые стандарты кодирования являются более строгими (и без очевидной цели), чем другие.
Mark Storer 17.09.2019 18:24:35

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

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

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

371
8.02.2019 14:14:20

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

face = 1 + randomNumbers.nextInt(6);
19
21.04.2016 06:01:47
rand.nextInt((max+1) - min) + min;

Это работает нормально.

13
21.04.2016 06:01:59

Прости меня за привередливость, но решение, предложенное большинством, то есть 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% или выше.

48
23.04.2018 05:21:33
Почему бы не создать исключение IllegalArgumentException, если разница = Integer.MAX_VALUE? Тогда вам не нужен цикл while.
M.P. Korstanje 9.01.2015 10:27:57
@mpkorstanje Эта реализация предназначена для работы с любыми значениями min <= max, даже если их разность равна или даже больше, чем MAX_VALUE. Выполнение цикла до достижения успеха в этом случае является обычной моделью, гарантирующей равномерное распределение (если основной источник случайности является равномерным). Random.nextInt (int) делает это внутренне, когда аргумент не является степенью 2.
Christian Semrau 6.05.2015 19:27:30
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);
}
17
8.02.2019 14:15:15

Другой вариант - просто использовать 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);
    // ...
 }
16
23.04.2018 05:22:28

Вот полезный класс для генерации случайных 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;
    }
}
19
15.02.2012 16:19:03

Я нашел этот пример Генерация случайных чисел :


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

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.
17
8.02.2019 14:14:44

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

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

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;
}
20
8.02.2019 14:14:37
// Since the random number is between the min and max values, simply add 1, Почему? Мин не считается? Обычно диапазон составляет [min, max), где min включено, а max исключено. Неправильный ответ, проголосовал вниз.
Maarten Bodewes 1.03.2017 21:26:35
@MaartenBodewes +1 добавлен, потому что getRandomNumberBetween генерирует случайное число, исключая предоставленные конечные точки.
Luke Taylor 2.03.2017 09:53:53
Число min + 1будет в два раза чаще, чем другое число, которое будет результатом getRandomNumberBetween!
Lii 17.06.2018 12:21:50

Вы можете использовать этот фрагмент кода, который решит вашу проблему:

Random r = new Random();
int myRandomNumber = 0;
myRandomNumber = r.nextInt(maxValue-minValue+1)+minValue;

Используйте myRandomNumber (который даст вам номер в диапазоне).

7
21.04.2016 06:03:04

Я просто генерирую случайное число с помощью Math.random () и умножаю его на большое число, скажем, 10000. Итак, я получаю число от 0 до 10000 и вызываю этот номер i. Теперь, если мне нужны числа между (x, y), сделайте следующее:

i = x + (i % (y - x));

Итак, все iчисла от x до y.

Чтобы убрать смещение, как указано в комментариях, вместо умножения его на 10000 (или большого числа), умножьте его на (yx).

4
20.12.2017 19:37:50

Один из моих друзей задал мне тот же вопрос в университете сегодня (его требованием было сгенерировать случайное число между 1 и -1). Итак, я написал это, и пока все отлично работает с моим тестированием. В идеале существует множество способов генерирования случайных чисел с заданным диапазоном. Попробуй это:

Функция:

private static float getRandomNumberBetween(float numberOne, float numberTwo) throws Exception{

    if (numberOne == numberTwo){
        throw new Exception("Both the numbers can not be equal");
    }

    float rand = (float) Math.random();
    float highRange = Math.max(numberOne, numberTwo);
    float lowRange = Math.min(numberOne, numberTwo);

    float lowRand = (float) Math.floor(rand-1);
    float highRand = (float) Math.ceil(rand+1);

    float genRand = (highRange-lowRange)*((rand-lowRand)/(highRand-lowRand))+lowRange;

    return genRand;
}

Выполните так:

System.out.println( getRandomNumberBetween(1,-1));
3
21.04.2016 06:03:26
Попробуйте другие диапазоны, ваш код не выдает одинаковые значения в данном диапазоне. numberOne = 3.5 и numberTwo = 7.2 выдают значения только в диапазоне 4.73..5.96.
Warren MacEvoy 17.08.2016 22:25:23

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

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

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

64
23.03.2020 20:50:41

Попробуйте использовать org.apache.commons.lang.RandomStringUtilsкласс. Да, иногда он дает повторяющееся число рядом, но это даст значение от 5 до 15:

    while (true)
    {
        int abc = Integer.valueOf(RandomStringUtils.randomNumeric(1));
        int cd = Integer.valueOf(RandomStringUtils.randomNumeric(2));
        if ((cd-abc) >= 5 && (cd-abc) <= 15)
        {
            System.out.println(cd-abc);
            break;
        }
    }
2
1.08.2013 18:07:15

Это можно сделать, просто выполнив утверждение:

Randomizer.generate(0,10); //min of zero, max of ten

Ниже приведен его исходный код

Randomizer.java

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

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

42
12.07.2019 18:20:03
Это могло быть редактированием другого примера, теперь это просто вопиющая копия репутации. Указание «ответа большинством голосов» также не очень прямое, оно может измениться.
Maarten Bodewes 19.06.2017 21:23:47
Это верно @MaartenBodewes. Когда я написал этот ответ, ответ с наибольшим количеством голосов все еще был написан в виде алгоритмического решения. Теперь решение выше сильно изменилось, и теперь этот ответ выглядел как подражатель.
Abel Callejo 20.06.2017 00:36:07
Я действительно не понимаю, почему такие фундаментальные фрагменты кода не являются частью стандартных библиотек Java. Почему я должен это реализовать?
Leevi L 8.10.2019 08:31:53

Я думаю, что этот код будет работать для него. Пожалуйста, попробуйте это:

import java.util.Random;
public final class RandomNumber {

    public static final void main(String... aArgs) {
        log("Generating 10 random integers in range 1..10.");
        int START = 1;
        int END = 10;
        Random randomGenerator = new Random();
        for (int idx=1; idx<=10; ++idx) {

            // int randomInt=randomGenerator.nextInt(100);
            // log("Generated : " + randomInt);
            showRandomInteger(START,END,randomGenerator);
        }
        log("Done");
    }

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

    private static void showRandomInteger(int aStart, int aEnd, Random aRandom) {
        if (aStart > aEnd) {
            throw new IllegalArgumentException("Start cannot exceed End.");
        }
        long range = (long)aEnd - (long)aStart + 1;
        long fraction = (long) (range * aRandom.nextDouble());
        int randomNumber = (int) (fraction + aStart);
        log("Generated" + randomNumber);
    }
}
3
21.04.2016 06:04:37

Я думаю, чтобы линейно нормализовать сгенерированные случайные числа в желаемом диапазоне, используя следующее. Позвольте xбыть случайным числом, пусть aи bбудет минимальный и максимальный диапазон желаемого нормализованного числа.

Ниже приведен лишь очень простой фрагмент кода для проверки диапазона, получаемого линейным отображением.

public static void main(String[] args) {
    int a = 100;
    int b = 1000;
    int lowest = b;
    int highest = a;
    int count = 100000;
    Random random = new Random();
    for (int i = 0; i < count; i++) {
        int nextNumber = (int) ((Math.abs(random.nextDouble()) * (b - a))) + a;
        if (nextNumber < a || nextNumber > b) {
            System.err.println("number not in range :" + nextNumber);
        }
        else {
            System.out.println(nextNumber);
        }
        if (nextNumber < lowest) {
            lowest = nextNumber;
        }
        if (nextNumber > highest) {
            highest = nextNumber;
        }
    }
    System.out.println("Produced " + count + " numbers from " + lowest
            + " to " + highest);
}
4
18.01.2014 12:47:07

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

Random ran = new Random();
// Assumes max and min are non-negative.
int randomInt = min + ran.nextInt(max - min + 1);
20
8.02.2019 14:15:11
Я не вижу здесь ничего нового, что не было опубликовано в бесчисленных предыдущих сообщениях.
Maarten Bodewes 19.06.2017 21:21:53

Я просто скажу, что не так с решениями, представленными в вопросе и почему ошибки.

Решение 1:

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

Проблема: для randomNum присваиваются значения чисел, превышающие максимальные.

Объяснение: Предположим, что наш минимум равен 5, а ваш максимум равен 10. Любое значение от Math.random()0,6 заставит выражение оценить значение 6 или больше, а при добавлении 5 оно будет больше 10 (ваш максимум). Проблема в том, что вы умножаете случайное число на максимум (который генерирует число почти такое же большое, как максимум), а затем добавляете минимум. Если минимум не равен 1, это не правильно. Вы должны переключиться на, как указано в других ответах

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

+1 потому Math.random()что никогда не вернет 1.0.

Решение 2:

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

Ваша проблема здесь в том, что «%» может возвращать отрицательное число, если первый член меньше 0. Так как rn.nextInt()возвращает отрицательные значения с вероятностью ~ 50%, вы также не получите ожидаемый результат.

Это было, однако, почти идеально. Вы просто должны были посмотреть немного дальше вниз по Javadoc, nextInt (int n) . С этим методом доступны, делая

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

Также вернул бы желаемый результат.

6
21.04.2016 06:04:59
% имеет еще большую проблему смещения распределения. Недавно я написал об этом в блоге: jaroslawpawlak.wordpress.com/2014/10/11/…
Jaroslaw Pawlak 9.03.2015 15:52:11

Вы можете использовать класс Random для генерации случайного числа, а затем использовать .nextInt (maxNumber) для генерации случайного числа. MaxNumber - это число, которое вы хотите максимум при генерации случайного числа. Пожалуйста, помните, что класс Random дает вам числа от 0 до maxNumber-1.

Random r = new Random();
int i = r.nextInt();

Другой способ сделать это - использовать класс Math.Random (), который требуется от многих классов в школах, потому что он более эффективен и вам не нужно объявлять новый объект Random. Чтобы получить случайное число с помощью Math.Random (), введите:

Math.random() * (max - min) + min;
2
21.04.2016 06:05:14
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
21.04.2016 06:05:22