Java:随机长数在0和lt=x & lt;n范围

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

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

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

这将生成一个大于或等于0小于100的整数。我想用长数字做同样的事情。

1
long y = magicRandomLongGenerator(100);

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


从Java 7(或Android API级别21=5 +)开始,您可以直接使用EDCOX1×0(0≤x<n)和EDCOX1≤1(对于m≤x<n)。详情请参见@alex的答案。

如果你被Java 6(或Android 4。x)所困扰,你需要使用一个外部的库(例如EDCOX1,2),参见@ MaWaldne的答案,或者实现你自己的EDCOX1 3。

根据http://java.sun.com/j2se/1.5.0/docs/api/java/util/random.html,nextInt实现为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 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

1
2
3
4
5
6
7
8
9
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:

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

将为您提供介于0(包含)和范围(不包含)之间的长整型。同样,如果您想要一个介于x和y之间的数字:

1
2
3
4
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)方法。

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

如果您需要0以外的来源,它也有nextLong(long origin, long bound)。传递源(包含)和绑定(排除)。

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

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


以上方法效果很好。如果您使用的是ApacheCommons(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)


使用"%"运算符

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

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

例如:

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


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

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

其中rand是你的随机对象。

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

由于nextLong()生成了一个均匀分布的伪随机长,范围在-(2^48)、2^48)(或在该范围内的某个地方),所以需要取其绝对值。否则,nextLong()方法的模有50%的机会返回负值,这超出了范围[0,m

您最初请求的是一个在[0100]范围内均匀分布的伪随机长。以下代码执行此操作:

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


非常感谢你的这篇文章。这正是我需要的。为了得到我以前工作过的那部分,我不得不换点东西。

我得到了以下信息(包括在上面):

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

将其更改为:

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

因为(long)r.nextDouble()总是零。


8从Java API

它可能是更容易,以实际执行API doc从http:////8 docs.oracle.com JavaSE /文档/ / / / random.html利用Java API #长长长长他们使用的是它生成的流出来。Origin可以和您的"0"型的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
}

下面的方法将返回1000000000到99999999之间的值

1
2
3
4
5
6
7
8
9
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
2
3
4
5
6
7
8
9
10
11
12
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;
}


进一步改进KYNYTM的回答:考虑到Java 8中的实际实现的子类实现将是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
  }
}


从随机页面:

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

1
2
3
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.

所以如果你想得到一个Long,你已经不能得到完整的64位范围了。

我建议,如果你有一个接近2次方的范围,你就建立一个Long,就像在这段代码中一样,如下所示:

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

例如,得到一个35位的范围。


1
2
3
4
5
6
7
8
9
10
11
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;
}


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

1
2
3
4
long number = (long) (rand.nextDouble()*max);


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

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

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

//循环直到得到大于或等于0且小于n的数字