Java Random giving negative numbers

Check out the documentation for java.util.Random:

http://download.oracle.com/javase/6/docs/api/java/util/Random.html

Are you you trying to get random numbers from 0 to 28? If so, you need to use nextInt(int) as mentioned previously. The seed has no bearing on the range of possible outputs or their relative likelihoods.


Since there is an equal chance of positive or negative numbers why not just:

Math.abs(rand.nextInt())

Nice and easy!


From the Java docs for nextInt():

All 232 possible int values are produced with (approximately) equal probability.

One approach is to use the following transform:

s =  rng.nextInt() & Integer.MAX_VALUE; // zero out the sign bit

The reason something like this is needed (as opposed to using absolute value or negation) is that Integer.MIN_VALUE is too large in absolute value to be turned into a positive integer. That is, due to overflow, Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE and Integer.MIN_VALUE == -Integer.MIN_VALUE. The above transformation preserves the approximately uniform distribution property: if you wrote a generate-and-test loop that just threw away Integer.MIN_VALUE and returned the absolute value of everything else, then the positive integers would be twice as likely as zero. By mapping Integer.MIN_VALUE to zero, that brings the probability of zero into line with the positive integers.

Here is another approach, which may actually be a tiny bit faster (although I haven't benchmarked it):

int s = rng.next(Integer.SIZE - 1); // Integer.SIZE == 32

This will generate an integer with 31 random low-order bits (and 0 as the 32nd bit, guaranteeing a non-negative value). However (as pointed out in the comment by jjb), since next(int) is a protected method of Random, you'll have to subclass Random to expose the method (or to provide a suitable proxy for the method):

public class MyRandom extends Random {
    public MyRandom() {}
    public MyRandom(int seed) { super(seed); }

    public int nextNonNegative() {
        return next(Integer.SIZE - 1);
    }
}

Another approach is to use a ByteBuffer that wraps a 4-byte array. You can then generate a random four bytes (by calling nextBytes(byte[])), zero out the sign bit, and then read the value as an int. I don't believe this offers any advantage over the above, but I thought I'd just throw it out there. It's basically the same as my first solution (that masks with Integer.MAX_VALUE).

In an earlier version of this answer, I suggested using:

int s = rng.nextInt(Integer.MAX_VALUE);

However, according to the docs this will generate integers in the range 0 (inclusive) to Integer.MAX_VALUE (exclusive). In other words, it won't generate the value Integer.MAX_VALUE. In addition, it turns out that next(int) is always going to be faster than nextInt(int).


Negative numbers are allowed - maybe you've read of the similar Random method nextInt( int ) which does limit the returned values to be zero or greater.

Tags:

Java

Random