Search code examples
javarandomrangelong-integer

Java: random long number in 0 <= x < n range


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.


Solution

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