Java:0 <= x < n 范围内的随机长数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2546078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: random long number in 0 <= x < n range
提问by Vilius Normantas
Random class has a method to generate random int in a given range. For example:
Random 类具有在给定范围内生成随机 int 的方法。例如:
Random r = new Random();
int x = r.nextInt(100);
This would generate an int number more or equal to 0 and less than 100. I'd like to do exactly the same with long number.
这将生成一个大于或等于 0 且小于 100 的 int 数字。我想对 long 数字做完全相同的事情。
long y = magicRandomLongGenerator(100);
Random class has only nextLong(), but it doesn't allow to set range.
Random 类只有 nextLong(),但它不允许设置范围。
采纳答案by kennytm
Starting from Java 7(or Android API Level 21 = 5.0+) you could directly use ThreadLocalRandom.current().nextLong(n)
(for 0 ≤ x < n) and ThreadLocalRandom.current().nextLong(m, n)
(for m ≤ x < n). See @Alex's answer for detail.
从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的回答。
If you are stuck with Java 6(or Android 4.x) you need to use an external library (e.g. org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1)
, see @mawaldne's answer), or implement your own nextLong(n)
.
如果您坚持使用Java 6(或 Android 4.x),则需要使用外部库(例如org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1)
,请参阅@mawaldne的回答),或实现您自己的nextLong(n)
.
According to https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Random.htmlnextInt
is implemented as
根据https://docs.oracle.com/javase/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;
}
So we may modify this to perform nextLong
:
所以我们可以修改它来执行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;
}
回答by M. Jessup
The standard method to generate a number (without a utility method) in a range is to just use the double with the range:
在范围内生成数字(不使用实用方法)的标准方法是仅使用带范围的双精度数:
long range = 1234567L;
Random r = new Random()
long number = (long)(r.nextDouble()*range);
will give you a long between 0 (inclusive) and range (exclusive). Similarly if you want a number between x and y:
会给你一个介于 0(包含)和范围(不包含)之间的 long。同样,如果您想要 x 和 y 之间的数字:
long x = 1234567L;
long y = 23456789L;
Random r = new Random()
long number = x+((long)(r.nextDouble()*(y-x)));
will give you a long from 1234567 (inclusive) through 123456789 (exclusive)
会给你一个从1234567(含)到123456789(不含)的长
Note: check parentheses, because casting to long has higher priority than multiplication.
注意:检查括号,因为转换为 long 的优先级高于乘法。
回答by Phil
From the page on Random:
从Random页面:
The method nextLong is implemented by class Random as if by:
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.
nextLong 方法由 Random 类实现,就像通过:
public long nextLong() { return ((long)next(32) << 32) + next(32); }
因为 Random 类使用只有 48 位的种子,所以该算法不会返回所有可能的长值。
So if you want to get a Long
, you're already not going to get the full 64 bit range.
因此,如果您想获得一个Long
,那么您已经无法获得完整的 64 位范围。
I would suggest that if you have a range that falls near a power of 2, you build up the Long
as in that snippet, like this:
我建议,如果您的范围接近 2 的幂,则Long
在该片段中构建as,如下所示:
next(32) + ((long)nextInt(8) << 3)
to get a 35 bit range, for example.
例如,获得 35 位范围。
回答by J Low
The methods using the r.nextDouble()
should use:
使用的方法r.nextDouble()
应该使用:
long number = (long) (rand.nextDouble()*max);
long number = x+(((long)r.nextDouble())*(y-x));
回答by mawaldne
The methods above work great. If you're using apache commons (org.apache.commons.math.random) check out RandomData. It has a method: nextLong(long lower, long upper)
上面的方法效果很好。如果您使用 apache 公共资源(org.apache.commons.math.random),请查看 RandomData。它有一个方法:nextLong(long lower, long upper)
http://commons.apache.org/math/userguide/random.html
回答by Septic Overflow
Use the '%' operator
使用“%”运算符
resultingNumber = (r.nextLong() % (maximum - minimum)) + minimum;
By using the '%' operator, we take the remainder when divided by your maximum value. This leaves us with only numbers from 0 (inclusive) to the divisor (exclusive).
通过使用“%”运算符,我们将得到除以最大值后的余数。这让我们只剩下从 0(含)到除数(不含)的数字。
For example:
例如:
public long randLong(long min, long max) {
return (new java.util.Random().nextLong() % (max - min)) + min;
}
回答by Valentinos Ioannou
//use system time as seed value to get a good random number
//使用系统时间作为种子值得到一个好的随机数
Random random = new Random(System.currentTimeMillis());
long x;
do{
x=random.nextLong();
}while(x<0 && x > n);
//Loop until get a number greater or equal to 0 and smaller than n
//循环直到得到一个大于等于0且小于n的数
回答by Alex
ThreadLocalRandom
ThreadLocalRandom
ThreadLocalRandom
has a nextLong(long bound)
method.
ThreadLocalRandom
有nextLong(long bound)
方法。
long v = ThreadLocalRandom.current().nextLong(100);
It also has nextLong(long origin, long bound)
if you need an origin other than 0. Pass the origin (inclusive) and the bound (exclusive).
nextLong(long origin, long bound)
如果您需要 0 以外的原点,它也有。传递原点(包含)和边界(不包含)。
long v = ThreadLocalRandom.current().nextLong(10,100); // For 2-digit integers, 10-99 inclusive.
SplittableRandom
has the same nextLong
methods and allows you to choose a seed if you want a reproducible sequence of numbers.
SplittableRandom
有相同的nextLong
方法,如果你想要一个可重复的数字序列,你可以选择一个种子。
回答by Enrice
Further improving kennytm's answer: A subclass implementation taking the actual implementation in Java 8 into account would be:
进一步改进 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;
}
}
回答by android developer
How about this:
这个怎么样:
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;
}
?
?