158

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.

Vilius Normantas
  • 3,708
  • 6
  • 25
  • 38
  • Related, may be useful: http://stackoverflow.com/questions/2290057/how-to-generate-a-random-biginteger-value-in-java – T.J. Crowder Mar 30 '10 at 14:46
  • 2
    Have you considered just getting your long random and taking the mod of your range? (Of course, if the range is only 100 I'd produce an int random and cast it to long.) – Hot Licks Apr 08 '12 at 13:05
  • `java.util.Random` only uses a 48 bit distribution (see implementation details), so it won't have a normal distribution. – Geoffrey De Smet May 16 '12 at 13:07
  • 1
    In the modern days one could consider using org.apache.commons.lang3.RandomUtils#nextLong. – reallynice Sep 04 '15 at 09:42

17 Answers17

184

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;
}
Marc Bannout
  • 388
  • 4
  • 15
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 2
    I'm having some problems with "2^x checking" part. Any ideas? – Vilius Normantas Mar 30 '10 at 19:45
  • @Vilius: The 2^x checking just makes the generation faster because directly using `rng.nextLong() % n` will be give uniform values (assume all bits are good). You can ignore that part if you want. – kennytm Mar 30 '10 at 20:07
  • If I want `m <= x <= n`, how would you modify your solution? – BJ Dela Cruz Aug 28 '14 at 22:05
  • 6
    @BJPeterDeLaCruz: A random number between `m` and `n` can be obtained with a random number between `0` and `n-m`, then add `m`. – kennytm Aug 29 '14 at 08:38
109

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Alex - GlassEditor.com
  • 14,957
  • 5
  • 49
  • 49
  • 8
    This answer much simpler and therefore more useful than the most voted one. – Yuriy N. Nov 10 '15 at 15:01
  • 2
    For those developing for Android, notice that it's available only from API 21 (Lollipop , Android 5.0) : http://developer.android.com/reference/java/util/concurrent/ThreadLocalRandom.html – android developer Apr 07 '16 at 14:47
  • ThreadLocalRandom is more secured than Random for concurrent programs. In "Effective Java" Joshua Bloch said that ThreadLocalRandom is also faster than Random. – Falcon May 09 '23 at 07:30
76

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.

rafalmag
  • 1,791
  • 1
  • 17
  • 24
M. Jessup
  • 8,153
  • 1
  • 29
  • 29
  • 6
    My first idea was exactly this. But it seems to be a bit inelegant. And I'm worried about uniformness of the distribution (it's not that I really need it, I just want to do it right) – Vilius Normantas Mar 30 '10 at 19:57
  • 8
    Please never use this. The output is not uniform at all. – Navin Dec 27 '15 at 07:38
  • 2
    The biggest problem is that rounding will make the lowest bit very nonuniform. Also, `bound` will have to be less than the largest integer that can be encoded in a double, 2^53. – Aleksandr Dubinsky Mar 25 '17 at 12:49
12

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

http://commons.apache.org/math/api-1.1/org/apache/commons/math/random/RandomData.html#nextLong(long,%20long)

mawaldne
  • 3,919
  • 6
  • 31
  • 37
  • 3
    For posterity: RandomData is deprecated in 4.0. Use http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/random/RandomDataGenerator.html – Michael Tontchev May 01 '15 at 16:11
11

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;
}
Septic Overflow
  • 135
  • 1
  • 4
  • This is nice, but you should check `if (max == min)` – khcpietro Apr 10 '14 at 15:00
  • And also check `if (nextLong() >= 0)` – khcpietro Apr 10 '14 at 15:19
  • 7
    FYI: This doesn't always give a uniform distribution, and it's really bad for some large ranges. For example, if `min = 0` and `max = 2 * (MAX_LONG / 3)`, then you're twice as likely to get a value in `[0, MAX_LONG / 3]` as you are to get one in `[MAX_LONG / 3, 2 * (MAX_LONG / 3)]`. – Nick May 21 '15 at 22:09
  • This code won't work. if `nextLong` returns a negative value, the remainder will be negative, and the value will be outside the range. – Arnaud May 25 '15 at 07:53
4

WARNING

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;
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
  • 2
    modulo is biased, do not use it for random https://stackoverflow.com/a/10984975/1166266 – Allison Dec 08 '18 at 09:11
  • 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. – Dave Jarvis Nov 29 '22 at 19:42
3

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;
  }
}
Enrice
  • 51
  • 7
  • I know this is an old answer and unlikely to be used, but this part is demonstrably incorrect: `if ((bound & m) == 0) { r = (bound * r) >> (Long.SIZE - 1); }` First, it's easy to show with unit tests that this does not actually produce numbers in the range [0, bound). Second, it's unnecessarily elaborate: `r = r & m` would accomplish the desired result, and that is basically what the current Java 8 implementation does. It's possible that the implementation was different when this answer was written, but it can't have been what's shown. – E. Bishop May 26 '20 at 23:43
2

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

?

android developer
  • 114,585
  • 152
  • 739
  • 1,270
2

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;

}
Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
Arpan Saini
  • 4,623
  • 1
  • 42
  • 50
2

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;
}
Vitaliy
  • 416
  • 6
  • 9
1

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.

Phil
  • 2,828
  • 1
  • 23
  • 20
  • 2
    But the documentation says "All 2^64 possible long values are produced with (approximately) equal probability." So apparently the nextLong() method should return all possible values.. Btw, how length of the seed is related to distribution of values? – Vilius Normantas Mar 30 '10 at 19:51
0

The methods using the r.nextDouble() should use:

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


long number = x+(((long)r.nextDouble())*(y-x));
Juan Mellado
  • 14,973
  • 5
  • 47
  • 54
J Low
  • 49
  • 1
0

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.

Sridhar Sg
  • 1,546
  • 13
  • 21
0
import java.util*;

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

This should work

David Buck
  • 3,752
  • 35
  • 31
  • 35
Liash101
  • 11
  • 1
0
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;
  }
PKS
  • 618
  • 1
  • 7
  • 19
-1
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;
}
XXX
  • 8,996
  • 7
  • 44
  • 53
  • 1
    You shouldn't create `Random` instances at hoc, you shouldn't catch `Throwable`s or other exceptions if not needed, you should log errors with some kind of logging framework (i.e. SLF4J) instead of using `printStackTrace`. – Boguś Sep 23 '17 at 15:05
-5

//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

  • 1
    This can be extremly inneficient. What if `n` is 1, or say 2? The loop will perform __many__ iterations. – Magnilex Oct 02 '15 at 13:03