Reputation: 3758
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.
Upvotes: 162
Views: 200950
Reputation: 1
Came across this post when looking at using new Random(3142L).longNext()
Looked at java jdk1.8.0_381 src where the line "...
from
" public long nextLong(){ return( (long)( next(32) )<<32 )+next( 32 ); } "
concerned me but when I looked at src for Random(seed) and .nextLong()
I came to think that though protected int next(bits) takes integer from Long only 48 bits of which is random bits, integer returned covers all value of an integer ie 0x0000->0xFFFF
Long returned by .nextLong() is constructed from two separate integers from .next() One placed as most significant int of Long and one placed as least significant int
As each int covers all values of integer I think all values of Long will be covered, though. So .nextLong() is adequate for returning all values of Long and better than Random documentation suggests.
As to your problem, Long has no advantages over int when working with numbers from 0-100. Casting .nextInt(100) to Long is probably the best solution
long[] aol=new long[0];
Random r=new Random();
long next(){ return (long)( r.nextInt(100) ); }
for(int i=0; i<100; i++){ aol[i++]=this.next(); }
Yields random array of 100 Long values
Upvotes: 0
Reputation: 523344
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.
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)
.
According to Random
documentation, nextInt
is implemented as
public int nextInt(int bound) {
if (bound <= 0)
throw new IllegalArgumentException("bound must be positive");
if ((bound & -bound) == bound) // i.e., bound is a power of 2
return (int)((bound * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % bound;
} while (bits - val + (bound-1) < 0);
return val;
}
So we may modify this to perform nextLong
:
long nextLong(Random rng, long bound) {
// error checking and 2^x checking removed for simplicity.
long bits, val;
do {
bits = (rng.nextLong() << 1) >>> 1;
val = bits % bound;
} while (bits-val+(bound-1) < 0L);
return val;
}
Upvotes: 186
Reputation: 67
Note that System.out.println(Math.abs(Integer.MIN_VALUE));
prints -2147483648, meaning that if rand.nextLong()
picks Integer.MIN_VALUE
, a negative value is returned. This is misleading because Math.abs()
does not return a positive number in all cases.
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;
Upvotes: 4
Reputation: 763
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;
}
Upvotes: 0
Reputation: 11
import java.util*;
Random rnd = new Random ();
long name = Math.abs(rnd.nextLong());
This should work
Upvotes: 0
Reputation: 1596
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.
Upvotes: 0
Reputation: 426
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;
}
Upvotes: 2
Reputation: 5191
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;
}
Upvotes: 2
Reputation: 15507
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.
Upvotes: 113
Reputation: 9072
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;
}
Upvotes: -1
Reputation: 116412
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;
}
?
Upvotes: 2
Reputation: 53
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;
}
}
Upvotes: 3
Reputation: 31
//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
Upvotes: -5
Reputation: 135
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;
}
Upvotes: 11
Reputation: 3998
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)
http://commons.apache.org/math/userguide/random.html
Upvotes: 12
Reputation: 8222
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.
Upvotes: 75
Reputation: 79
The methods using the r.nextDouble()
should use:
long number = (long) (rand.nextDouble()*max);
long number = x+(((long)r.nextDouble())*(y-x));
Upvotes: 0
Reputation: 2927
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.
Upvotes: 1