Java: random long number in 0 <= x < n range
Random类有一个在给定范围内生成随机int的方法。例如:
这将生成一个大于或等于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,
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; } |
因此,我们可以修改此项以执行
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:
将为您提供介于0(包含)和范围(不包含)之间的长整型。同样,如果您想要一个介于x和y之间的数字:
1 2 3 4 |
将给您一个从1234567(含)到123456789(不含)的长整数
注意:检查括号,因为强制转换为long的优先级高于乘法。
1 | long v = ThreadLocalRandom.current().nextLong(100); |
如果您需要0以外的来源,它也有
1 | long v = ThreadLocalRandom.current().nextLong(10,100); // For 2-digit integers, 10-99 inclusive. |
以上方法效果很好。如果您使用的是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,
1 |
其中
模运算符将两个数相除,并输出这些数的余数。例如,
由于
您最初请求的是一个在[0100]范围内均匀分布的伪随机长。以下代码执行此操作:
1 |
非常感谢你的这篇文章。这正是我需要的。为了得到我以前工作过的那部分,我不得不换点东西。
我得到了以下信息(包括在上面):
1 | long number = x+((long)r.nextDouble()*(y-x)); |
将其更改为:
1 | long number = x+ (long)(r.nextDouble()*(y-x)); |
因为
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 |
这个怎么样?
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.
所以如果你想得到一个
我建议,如果你有一个接近2次方的范围,你就建立一个
1 | next(32) + ((long)nextInt(8) << 3) |
例如,得到一个35位的范围。
1 2 3 4 5 6 7 8 9 10 11 |
使用
1 2 3 4 | long number = (long) (rand.nextDouble()*max); long number = x+(((long)r.nextDouble())*(y-x)); |
//使用系统时间作为种子值得到一个好的随机数
1 2 3 4 5 |
//循环直到得到大于或等于0且小于n的数字