151

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

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

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

long y = magicRandomLongGenerator(100);

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

4

16 回答 16

175

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的答案。


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

根据https://docs.oracle.com/javase/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;
}
于 2010-03-30T14:55:20.840 回答
96

ThreadLocalRandom

ThreadLocalRandomnextLong(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方法,如果您想要可重复的数字序列,则允许您选择种子。

于 2015-07-28T17:10:13.090 回答
75

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

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

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

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

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

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

于 2010-03-30T14:51:54.187 回答
12

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

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)

于 2012-07-31T19:44:54.003 回答
11

使用“%”运算符

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

通过使用“%”运算符,我们会在除以您的最大值时取余数。这让我们只有从 0(包括)到除数(不包括)的数字。

例如:

public long randLong(long min, long max) {
    return (new java.util.Random().nextLong() % (max - min)) + min;
}
于 2013-10-09T01:31:49.057 回答
3

进一步改进 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;
  }
}
于 2015-10-02T11:41:13.060 回答
3

如果您想要一个在 [0, m) 范围内的均匀分布的伪随机数,请尝试使用模运算符和绝对值方法结合nextLong()如下所示的方法:

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

rand你的 Random 对象在哪里。

模运算符将两个数字相除并输出这些数字的余数。例如,3 % 21因为 3 和 2 的余数是 1。

由于nextLong()在 [-(2^48),2^48) 范围内(或该范围内的某个位置)生成一个均匀分布的伪随机数,因此您需要取它的绝对值。如果不这样做,该nextLong()方法的模有 50% 的机会返回负值,该值超出范围 [0, m)。

您最初要求的是在 [0,100) 范围内的均匀分布的伪随机数。下面的代码就是这样做的:

Math.abs(rand.nextLong()) % 100;
于 2017-03-14T03:44:59.333 回答
2

这个怎么样:

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

?

于 2016-04-07T14:38:46.913 回答
2

下面的方法将返回一个介于 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;

}
于 2017-06-22T00:37:32.903 回答
2

来自Java 8 API

API 文档 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;
}
于 2018-10-09T23:41:23.967 回答
1

Random页面:

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

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

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

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

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

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

例如,获得 35 位范围。

于 2010-03-30T14:55:24.740 回答
0

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

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


long number = x+(((long)r.nextDouble())*(y-x));
于 2012-04-08T12:18:57.530 回答
0
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;
}
于 2016-06-12T10:11:44.040 回答
0

如果您可以使用 java 流,您可以尝试以下方法:

Random randomizeTimestamp = new Random();
Long min = ZonedDateTime.parse("2018-01-01T00:00:00.000Z").toInstant().toEpochMilli();
Long max = ZonedDateTime.parse("2019-01-01T00:00:00.000Z").toInstant().toEpochMilli();
randomizeTimestamp.longs(generatedEventListSize, min, max).forEach(timestamp -> {
  System.out.println(timestamp);
});

这将在给定范围内生成长整数。

于 2019-10-18T07:56:26.563 回答
0
import java.util*;

    Random rnd = new Random ();
    long name = Math.abs(rnd.nextLong());

这应该工作

于 2020-06-19T12:39:03.707 回答
-4

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

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

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

于 2015-07-20T22:39:51.047 回答