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

问题

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

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

这将产生一个大于或等于0且小于100的int数。我想用长数做同样的事。

long y = magicRandomLongGenerator(100);

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


#1 热门回答(121 赞)

Java 7(或Android API Level 21 = 5.0)开始,你可以直接使用ThreadLocalRandom.current().nextLong(n)(对于0≤x<n)和ThreadLocalRandom.current().nextLong(m, n)(对于m≤x<n)。有关详细信息,请参阅@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.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;
}

#2 热门回答(72 赞)

在一个范围内生成数字(没有实用方法)的标准方法是只使用范围为的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具有比乘法更高的优先级。


#3 热门回答(54 赞)

#ThreadLocalRandom

ThreadLocalRandom是anextLong(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具有相同的99458567方法,如果你想要可重复的数字序列,则允许你选择种子。