Java:0 <= x < n 范围内的随机长数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2546078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:08:06  来源:igfitidea点击:

Java: random long number in 0 <= x < n range

javarandomrangelong-integer

提问by Vilius Normantas

Random class has a method to generate random int in a given range. For example:

Random 类具有在给定范围内生成随机 int 的方法。例如:

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

This would generate an int number more or equal to 0 and less than 100. I'd like to do exactly the same with long number.

这将生成一个大于或等于 0 且小于 100 的 int 数字。我想对 long 数字做完全相同的事情。

long y = magicRandomLongGenerator(100);

Random class has only nextLong(), but it doesn't allow to set range.

Random 类只有 nextLong(),但它不允许设置范围。

采纳答案by kennytm

Starting from Java 7(or Android API Level 21 = 5.0+) you could directly use ThreadLocalRandom.current().nextLong(n)(for 0 ≤ x < n) and ThreadLocalRandom.current().nextLong(m, n)(for m ≤ x < n). See @Alex's answer for detail.

Java 7(或 Android API Level 21 = 5.0+)开始,您可以直接使用ThreadLocalRandom.current().nextLong(n)(for 0 ≤ x < n) 和ThreadLocalRandom.current().nextLong(m, n)(for m ≤ x < n)。有关详细信息,请参阅@Alex的回答。



If you are stuck with Java 6(or Android 4.x) you need to use an external library (e.g. org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1), see @mawaldne's answer), or implement your own nextLong(n).

如果您坚持使用Java 6(或 Android 4.x),则需要使用外部库(例如org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1),请参阅@mawaldne的回答),或实现您自己的nextLong(n).

According to https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Random.htmlnextIntis implemented as

根据https://docs.oracle.com/javase/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;
 }

So we may modify this to perform nextLong:

所以我们可以修改它来执行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;
}

回答by M. Jessup

The standard method to generate a number (without a utility method) in a range is to just use the double with the range:

在范围内生成数字(不使用实用方法)的标准方法是仅使用带范围的双精度数:

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

will give you a long between 0 (inclusive) and range (exclusive). Similarly if you want a number between x and y:

会给你一个介于 0(包含)和范围(不包含)之间的 long。同样,如果您想要 x 和 y 之间的数字:

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

will give you a long from 1234567 (inclusive) through 123456789 (exclusive)

会给你一个从1234567(含)到123456789(不含)的长

Note: check parentheses, because casting to long has higher priority than multiplication.

注意:检查括号,因为转换为 long 的优先级高于乘法。

回答by Phil

From the page on Random:

Random页面:

The method nextLong is implemented by class Random as if by:

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

Because class Random uses a seed with only 48 bits, this algorithm will not return all possible long values.

nextLong 方法由 Random 类实现,就像通过:

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

因为 Random 类使用只有 48 位的种子,所以该算法不会返回所有可能的长值。

So if you want to get a Long, you're already not going to get the full 64 bit range.

因此,如果您想获得一个Long,那么您已经无法获得完整的 64 位范围。

I would suggest that if you have a range that falls near a power of 2, you build up the Longas in that snippet, like this:

我建议,如果您的范围接近 2 的幂,则Long在该片段中构建as,如下所示:

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

to get a 35 bit range, for example.

例如,获得 35 位范围。

回答by J Low

The methods using the r.nextDouble()should use:

使用的方法r.nextDouble()应该使用:

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


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

回答by mawaldne

The methods above work great. If you're using apache commons (org.apache.commons.math.random) check out RandomData. It has a method: nextLong(long lower, long upper)

上面的方法效果很好。如果您使用 apache 公共资源(org.apache.commons.math.random),请查看 RandomData。它有一个方法:nextLong(long lower, long upper)

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

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)

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

回答by Septic Overflow

Use the '%' operator

使用“%”运算符

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

By using the '%' operator, we take the remainder when divided by your maximum value. This leaves us with only numbers from 0 (inclusive) to the divisor (exclusive).

通过使用“%”运算符,我们将得到除以最大值后的余数。这让我们只剩下从 0(含)到除数(不含)的数字。

For example:

例如:

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

回答by Valentinos Ioannou

//use system time as seed value to get a good random number

//使用系统时间作为种子值得到一个好的随机数

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

//Loop until get a number greater or equal to 0 and smaller than n

//循环直到得到一个大于等于0且小于n的数

回答by Alex

ThreadLocalRandom

ThreadLocalRandom

ThreadLocalRandomhas a nextLong(long bound)method.

ThreadLocalRandomnextLong(long bound)方法。

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

It also has nextLong(long origin, long bound)if you need an origin other than 0. Pass the origin (inclusive) and the bound (exclusive).

nextLong(long origin, long bound)如果您需要 0 以外的原点,它也有。传递原点(包含)和边界(不包含)。

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

SplittableRandomhas the same nextLongmethods and allows you to choose a seed if you want a reproducible sequence of numbers.

SplittableRandom有相同的nextLong方法,如果你想要一个可重复的数字序列,你可以选择一个种子。

回答by Enrice

Further improving kennytm's answer: A subclass implementation taking the actual implementation in Java 8 into account would be:

进一步改进 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;
  }
}

回答by android developer

How about this:

这个怎么样:

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

?

?