Java: случайное длинное число в диапазоне 0 <= x <n - PullRequest
119 голосов
/ 30 марта 2010

Случайный класс имеет метод для генерации случайного int в заданном диапазоне. Например:

Random r = new Random(); 
int x = r.nextInt(100);

Это сгенерирует целое число больше или равное 0 и меньше 100. Я хотел бы сделать то же самое с длинным числом.

long y = magicRandomLongGenerator(100);

Случайный класс имеет только nextLong (), но не позволяет устанавливать диапазон.

Ответы [ 15 ]

136 голосов
/ 30 марта 2010

Начиная с Java 7 (или Android API Level 21 = 5.0+), вы можете напрямую использовать ThreadLocalRandom.current().nextLong(n) (для 0 ≤ x ThreadLocalRandom.current().nextLong(m, n) (для m ≤ x @ Alex .


Если вы застряли с Java 6 (или Android 4.x), вам нужно использовать внешнюю библиотеку (например, org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1), см. Ответ @ mawaldne ), или реализовать свой собственный nextLong(n).

Согласно http://java.sun.com/j2se/1.5.0/docs/api/java/util/Random.html nextInt реализовано как

 public int nextInt(int n) {
     if (n<=0)
                throw new IllegalArgumentException("n must be positive");

     if ((n & -n) == n)  // i.e., n is a power of 2
         return (int)((n * (long)next(31)) >> 31);

     int bits, val;
     do {
         bits = next(31);
         val = bits % n;
     } while(bits - val + (n-1) < 0);
     return val;
 }

Таким образом, мы можем изменить это для выполнения nextLong:

long nextLong(Random rng, long n) {
   // error checking and 2^x checking removed for simplicity.
   long bits, val;
   do {
      bits = (rng.nextLong() << 1) >>> 1;
      val = bits % n;
   } while (bits-val+(n-1) < 0L);
   return val;
}
73 голосов
/ 30 марта 2010

Стандартный метод генерации числа (без использования вспомогательного метода) в диапазоне - просто использовать двойное с диапазоном:

long range = 1234567L;
Random r = new Random()
long number = (long)(r.nextDouble()*range);

даст вам длинную позицию от 0 (включительно) до диапазона (эксклюзив). Точно так же, если вы хотите число между х и у:

long x = 1234567L;
long y = 23456789L;
Random r = new Random()
long number = x+((long)(r.nextDouble()*(y-x)));

даст вам длинную позицию от 1234567 (включительно) до 123456789 (эксклюзив)

Примечание: проверьте круглые скобки, потому что приведение к long имеет более высокий приоритет, чем умножение.

63 голосов
/ 28 июля 2015

ThreadLocalRandom

ThreadLocalRandom имеет метод nextLong(long bound).

long v = ThreadLocalRandom.current().nextLong(100);

Он также имеет nextLong(long origin, long bound), если вам нужен источник, отличный от 0. Передайте источник (включительно) и связанный (эксклюзив).

long v = ThreadLocalRandom.current().nextLong(10,100); // For 2-digit integers, 10-99 inclusive.

SplittableRandom имеет те же методы nextLong и позволяет вам выбирать начальное число, если вы хотите воспроизводимую последовательность чисел.

12 голосов
/ 31 июля 2012

Методы выше работают отлично. Если вы используете Apache Commons (org.apache.commons.math.random), проверьте RandomData. У него есть метод: nextLong (длинный нижний, длинный верхний)

http://commons.apache.org/math/userguide/random.html

http://commons.apache.org/math/api-1.1/org/apache/commons/math/random/RandomData.html#nextLong(long,%20long)

11 голосов
/ 09 октября 2013

Используйте оператор '%'

resultingNumber = (r.nextLong() % (maximum - minimum)) + minimum;

Используя оператор '%', мы берем остаток от деления на ваше максимальное значение. Это оставляет нам только цифры от 0 (включительно) до делителя (исключая).

Например:

public long randLong(long min, long max) {
    return (new java.util.Random().nextLong() % (max - min)) + min;
}
2 голосов
/ 14 марта 2017

Если вам нужен равномерно распределенный псевдослучайный тип long в диапазоне [0, m), попробуйте использовать оператор по модулю и метод абсолютного значения в сочетании с методом nextLong(), как показано ниже:

Math.abs(rand.nextLong()) % m;

Где rand - ваш Случайный объект.

Оператор по модулю делит два числа и выводит остаток от этих чисел. Например, 3 % 2 равно 1, потому что остаток от 3 и 2 равен 1.

Поскольку nextLong() генерирует равномерно распределенное псевдослучайное длинное в диапазоне [- (2 ^ 48), 2 ^ 48) (или где-то в этом диапазоне), вам необходимо принять его абсолютное значение. Если вы этого не сделаете, по модулю метода nextLong() с вероятностью 50% можно вернуть отрицательное значение, выходящее за пределы диапазона [0, m).

То, что вы первоначально запрашивали, было равномерно распределенным псевдослучайным длинным в диапазоне [0,100). Следующий код делает это:

Math.abs(rand.nextLong()) % 100;
2 голосов
/ 01 апреля 2011

Большое спасибо за этот пост. Это именно то, что мне было нужно. Нужно было что-то изменить, чтобы получить часть, с которой я работал.

Я получил следующее (включено выше):

long number = x+((long)r.nextDouble()*(y-x));

для работы, изменив его на:

long number = x+ (long)(r.nextDouble()*(y-x));

, поскольку (long)r.nextDouble() всегда равно нулю.

1 голос
/ 10 октября 2018

С Java 8 API

Может быть проще взять фактическую реализацию из API doc https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long- они используют его для генерации длинного потока. И ваше происхождение может быть "0", как в вопросе.

long nextLong(long origin, long bound) {
  long r = nextLong();
  long n = bound - origin, m = n - 1;
  if ((n & m) == 0L)  // power of two
    r = (r & m) + origin;
  else if (n > 0L) {  // reject over-represented candidates
    for (long u = r >>> 1;            // ensure nonnegative
         u + m - (r = u % n) < 0L;    // rejection check
         u = nextLong() >>> 1) // retry
        ;
    r += origin;
  }
  else {              // range not representable as long
    while (r < origin || r >= bound)
      r = nextLong();
  }
  return r;
}
1 голос
/ 22 июня 2017

Приведенный ниже метод вернет вам значение от 10000000000 до 9999999999

long min = 1000000000L
long max = 9999999999L    

public static long getRandomNumber(long min, long max){

    Random random = new Random();         
    return random.nextLong() % (max - min) + max;

}
1 голос
/ 07 апреля 2016

Как насчет этого:

public static long nextLong(@NonNull Random r, long min, long max) {
    if (min > max)
        throw new IllegalArgumentException("min>max");
    if (min == max)
        return min;
    long n = r.nextLong();
    //abs (use instead of Math.abs, which might return min value) :
    n = n == Long.MIN_VALUE ? 0 : n < 0 ? -n : n;
    //limit to range:
    n = n % (max - min);
    return min + n;
}

...