Java: случайное длинное число в 0

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

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

это создаст число int больше или равно 0 и меньше 100. Я хотел бы сделать то же самое с long number.

long y = magicRandomLongGenerator(100);

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

14 ответов


начиная от 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.х) нужно использовать внешнюю библиотеку (например,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.htmlnextInt реализуется как

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

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

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

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

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

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

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


ThreadLocalRandom

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

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

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

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

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


методы выше работают отлично. Если вы используете Apache commons (org.апаш.палата общин.математика.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)


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

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

используя оператор"%", мы берем остаток при делении на максимальное значение. Это оставляет нам только числа от 0 (включительно) до делителя (исключающего).

например:

public long randLong(long min, long max) {
    return (new java.util.Random().nextLong() % (max - min)) + min;
}

Спасибо за этот пост. Это как раз то, что мне нужно. Нужно было что-то изменить, чтобы получить роль, которую я использовал для работы.

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

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

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

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

С (long)r.nextDouble() всегда равен нулю.


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

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

здесь rand ваш случайный объект.

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

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

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

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

со страницы на случайные:

метод nextLong реализуется классом Random как бы по:

public long nextLong() {
   return ((long)next(32) << 32) + next(32);
}

поскольку класс Random использует семя только с 48 битами, этот алгоритм не будет возвращать все возможные длинные значения.

Итак, если вы хотите получить Long, вы уже не получите полный 64-битный диапазон.

Я бы предположил, что если у вас есть диапазон, который падает вблизи мощности 2, вы создаете the Long как в этом фрагменте, как это:

next(32) + ((long)nextInt(8) << 3)

чтобы получить 35-битный диапазон, например.


дальнейшее улучшение ответа kennytm: реализация подкласса с учетом фактической реализации в Java 8 будет:

public class MyRandom extends Random {
  public long nextLong(long bound) {
    if (bound <= 0) {
      throw new IllegalArgumentException("bound must be positive");
    }

    long r = nextLong() & Long.MAX_VALUE;
    long m = bound - 1L;
    if ((bound & m) == 0) { // i.e., bound is a power of 2
      r = (bound * r) >> (Long.SIZE - 1);
    } else {
      for (long u = r; u - (r = u % bound) + m < 0L; u = nextLong() & Long.MAX_VALUE);
    }
    return r;
  }
}

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

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

?


методы, использующие r.nextDouble() должны использовать:

long number = (long) (rand.nextDouble()*max);


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

public static long randomLong(long min, long max)
{
    try
    {
        Random  random  = new Random();
        long    result  = min + (long) (random.nextDouble() * (max - min));
        return  result;
    }
    catch (Throwable t) {t.printStackTrace();}
    return 0L;
}

приведенный ниже метод вернет вам значение от 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;

}

/ / используйте системное время в качестве начального значения, чтобы получить хорошее случайное число

   Random random = new Random(System.currentTimeMillis());
              long x;
             do{
                x=random.nextLong();
             }while(x<0 && x > n); 

//цикл до получения числа больше или равно 0 и меньше, чем n