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

随机类有一个在给定范围内生成随机整型的方法,例如:

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

这将生成一个大于或等于0且小于100的 int 数。我想对长号码做同样的处理。

long y = magicRandomLongGenerator(100);

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

179351 次浏览

在一个范围内生成一个数字的标准方法(不使用实用方法)是只使用带范围的双精度数:

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

将为您提供0(包含)和范围(独占)之间的长度。类似地,如果你想要 x 和 y 之间的一个数:

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

将给你一个长期从1234567(包括)到123456789(独家)

注意: 检查括号,因为强制转换为 long 的优先级高于乘法。

爪哇7(或 Android API Level 21 = 5.0 +)开始,您可以直接使用 ThreadLocalRandom.current().nextLong(n)(0≤ x < n)和 ThreadLocalRandom.current().nextLong(m, n)(m ≤ x < n)。详见 @ Alex的答案。


如果你被 爪哇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.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;
}

因此,我们可以修改它来执行 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;
}

来自 随机的页面:

NextLong 方法是通过类 Random 实现的,就好像是通过:

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

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

因此,如果你想得到一个 Long,你已经不会得到完整的64位范围。

我建议,如果你有一个接近2的幂的范围,你建立起 Long,就像这个片段一样,像这样:

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

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

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

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




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

上述方法很有效。如果您正在使用 apache commons (org.apache.commons. math.Random) ,请查看 RRandom Data。它有一个方法: nextLong (long low,long above)

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

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

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

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

ThreadLocalRandom

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

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

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

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

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

进一步改进 kennytm 的回答: 考虑到 Java8中的实际实现的子类实现如下:

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

这样吧:

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

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

警告

请注意,System.out.println(Math.abs(Integer.MIN_VALUE));打印 -2147483648,这意味着如果 rand.nextLong()选择 Integer.MIN_VALUE,则返回负值。这是误导性的,因为 Math.abs()并不是在所有情况下都返回一个正数。


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

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

其中 rand是随机对象。

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

由于 nextLong()在[-(2 ^ 48) ,2 ^ 48)(或者在这个范围内的某个地方)生成一个均匀分布的伪随机,你需要求出它的绝对值。如果不这样做,nextLong()方法的模有50% 的几率返回负值,这超出了[0,m)的范围。

您最初请求的是一个均匀分布的伪随机,长度在[0,100]范围内:

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

下面的方法将返回一个介于1000000000到99999999之间的值

long min = 1000000000L
long max = 9999999999L


public static long getRandomNumber(long min, long max){


Random random = new Random();
return random.nextLong() % (max - min) + max;


}

来自 爪哇8 API

空气污染指数文件 < a href = “ https://docs.oracle.com/javase/8/docs/api/java/util/Rodd.html # longs-long-long-long-”rel = “ nofollow norefrer”> 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;
}

如果你可以使用 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);
});

这将在给定的长度范围内生成数字。

import java.util*;


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

这个应该可以

public static Long generate(int length) {
StringBuilder sb = new StringBuilder("1");
sb.setLength(length + 1);
String padded = sb.toString().replaceAll("[^0-9]", "0");
long rand = 0;
try {
rand = (long) (Math.random()*Long.valueOf(padded));
} catch (Exception e) {
}
return rand;
}