Random class has a method to generate random int in a given range. For example:
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.
long y = magicRandomLongGenerator(100);
Random class has only nextLong(), but it doesn't allow to set range.
This question is related to
java
random
range
long-integer
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;
}
Further improving kennytm's answer: A subclass implementation taking the actual implementation in Java 8 into account would be:
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;
}
}
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;
}
?
If you want a uniformly distributed pseudorandom long in the range of [0,m
), try using the modulo operator and the absolute value method combined with the nextLong()
method as seen below:
Math.abs(rand.nextLong()) % m;
Where rand
is your Random object.
The modulo operator divides two numbers and outputs the remainder of those numbers. For example, 3 % 2
is 1
because the remainder of 3 and 2 is 1.
Since nextLong()
generates a uniformly distributed pseudorandom long in the range of [-(2^48),2^48) (or somewhere in that range), you will need to take the absolute value of it. If you don't, the modulo of the nextLong()
method has a 50% chance of returning a negative value, which is out of the range [0,m
).
What you initially requested was a uniformly distributed pseudorandom long in the range of [0,100). The following code does so:
Math.abs(rand.nextLong()) % 100;
The below Method will Return you a value between 10000000000 to 9999999999
long min = 1000000000L
long max = 9999999999L
public static long getRandomNumber(long min, long max){
Random random = new Random();
return random.nextLong() % (max - min) + max;
}
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)
From Java 8 API
It could be easier to take actual implementation from API doc https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long- they are using it to generate longs stream. And your origin can be "0" like in the question.
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;
}
//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
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).
For example:
public long randLong(long min, long max) {
return (new java.util.Random().nextLong() % (max - min)) + min;
}
The methods using the r.nextDouble()
should use:
long number = (long) (rand.nextDouble()*max);
long number = x+(((long)r.nextDouble())*(y-x));
From the page on 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.
So if you want to get a Long
, you're already not going to get the full 64 bit range.
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:
next(32) + ((long)nextInt(8) << 3)
to get a 35 bit range, for example.
import java.util*;
Random rnd = new Random ();
long name = Math.abs(rnd.nextLong());
This should work
ThreadLocalRandom
ThreadLocalRandom
has a nextLong(long bound)
method.
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).
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.
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:
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)
Note: check parentheses, because casting to long has higher priority than multiplication.
If you can use java streams, you can try the following:
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);
});
This will generate numbers in the given range for longs.
Source: Stackoverflow.com