Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's up with this broken Java Random.nextInt(long) behavior?

Tags:

java

random

I discovered the hard way that this method seems to fail miserably when you feed it a power of 2. Given two Random objects of different seeds, it seems that the first integer they return when asked to return an integer between 0 (inclusive) and and a power of two (exclusive) is always the same; the seeds don't matter. For example:

public static void main(String[] args) {
    Random mRandom;
    for (int i = 0; i < 10; i++) {
        mRandom = new Random(i);            
        System.out.println(mRandom.nextInt((int) Math.pow(2, 4)));
    }
}

Console:
11
11
11
11
11
11
11
11
11
11

I chose 2^4 arbitrarily, but it seems to work for any power of two. What's going on? Furthermore, how can I avoid this?

like image 753
Nick Holt Avatar asked Nov 18 '13 06:11

Nick Holt


People also ask

How do you generate a random number between 1000 and 9999 in Java?

int randomNumber = ( int )( Math. random() * 9999 ); if( randomNumber <= 1000 ) { randomNumber = randomNumber + 1000; Math. random() is a method that generates a random number through a formula.

What does nextInt do in Java random?

nextInt. Returns the next pseudorandom, uniformly distributed int value from this random number generator's sequence.

How do you generate a random number from 1 to 10 in Java?

Java Random number between 1 and 10 Below is the code showing how to generate a random number between 1 and 10 inclusive. Random random = new Random(); int rand = 0; while (true){ rand = random. nextInt(11); if(rand != 0) break; } System.

Is random nextInt inclusive Java?

util. Random. nextInt(int n) : The nextInt(int n) is used to get a random number between 0(inclusive) and the number passed in this argument(n), exclusive.


1 Answers

This problem occurs due to 2 reasons.

  1. Same seed for Random class.
  2. At nextInt(int n), if n is power of 2

1. Same seed for Random class.

Because, you have initiated new Random instance with new seed value which has influence on the nextInt value generation. According to Java docs of Random(long seed).

Creates a new random number generator using a single long seed. The seed is the initial value of the internal state of the pseudorandom number generator which is maintained by method next(int).

The invocation new Random(seed) is equivalent to:

 Random rnd = new Random();
 rnd.setSeed(seed);

If you try to generate random value, without new seed than it will generate real random value, even though new instance of Random class.

for (int i = 0; i < 10; i++) {
    mRandom = new Random();   // Without seed         
    System.out.println(mRandom.nextInt((int) Math.pow(2, 4)));
}

Output: 2 1 12 4 3 9 9 8 2 9

2. At nextInt(int n), if n is power of 2

Besides this, Random#nextInt has effect of power of 2. If n is a power of 2 it will return (int)((n * (long)next(31)) >> 31) which will always same for same n. According to nextInt Algorithm,

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;
 }
like image 180
Masudul Avatar answered Oct 27 '22 00:10

Masudul