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

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

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

这将产生一个大于或等于0且小于100的整数。我想用长号完全相同。

 long y = magicRandomLongGenerator(100); 

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

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.html,nextInt被实现为;

  public int nextInt(int n) { if (n<=0) throw new IllegalArgumentException("n must be positive"); if ((n & -n) == n) // ie, 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; } 

在一个范围内生成一个数字(没有实用方法)的标准方法是只使用范围为:

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

会给你一个介于0(含)和range(含)之间的长时间。 同样,如果你想要一个x和y之间的数字:

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

会给你从1234567(含)到123456789(不含)

注意:检查括号,因为铸造长期比乘法有更高的优先级。

ThreadLocalRandom

ThreadLocalRandom有一个nextLong(long bound)方法。

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

如果你需要一个不是0的nextLong(long origin, long bound)它也有nextLong(long origin, long bound)传递原点(包含)和绑定(exclusive)。

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

SplittableRandom具有相同的nextLong方法,并允许您select一个种子,如果你想要一个可重复的数字序列。

上面的方法工作很好。 如果您使用的是Apache Commons(org.apache.commons.math.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()*(yx)); 

通过将其更改为:

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

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

从随机页面:

nextLong方法是通过类Random来实现的,就像通过:

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

由于Random类只使用48位的种子,因此该algorithm不会返回所有可能的长整型值。

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

我build议,如果你的射程接近2的幂,那么就像在这个片段中构buildLong一样:

 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) { // ie, 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())*(yx)); 
 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; } 

如果你想要一个在[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; 

下面的方法将返回一个10000000000到9999999999之间的值

  long MinimumNumber = 1000000000L long MaxiumNumber = 9999999999L public static long getRandomNumber(long MinimumNumber , long maxium){ Random random = new Random(); return random.nextLong() % (maxium - MinimumNumber) + maxium; } 

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

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

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