简体   繁体   中英

Java Random giving negative numbers

I'm having trouble with Javas Random class, if i do this:

Random rng = new Random(seed) // seed == 29 in this example

String ss = "";
        for(int i = 0; i < 10; i++)
        {
            int s = rng.nextInt();
            ss += Integer.toString(s);
            ss +="\n";
        }

This is what i get back:

-1169335537
-2076183625
1478047223
1914482305
722089687
2094672350
-1234724057
-1614953544
-321574001
1000360613

From what I have read this should only be returning positive numbers for a start?

This may be a bit far fetched but it couldnt have anything to do with running a 64 bit machine on Windows 7 64 bit?

Any help at all would be awesome need to get this finished for an assignment hand in today!

From the Java docs for nextInt() :

All 2 32 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 32 nd 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) .

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

Math.abs(rand.nextInt())

Nice and easy!

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.

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.

int s = rng.nextInt(bound); //bound 29 in this case

This will have a bound of 0 to 29 .

If you happen to work with numbers that have the possibility of having a negative value you can turn it into a positive value using a conditional declaration automatically by multiplying the value to a negative one. You can also turn a positive into a negative value using this same method.

The examples are below.

int a = -5;
a = a < 0? ( a == -2147483648? 0 : -a ) 
           : a;

int b = -2147483648;
b = b < 0? ( b == -2147483648? 0 : -b ) 
           : b;

int c = 12345;
c = c < 0? ( c == -2147483648? 0 : -c ) 
           : c;

Per the documentation http://download.oracle.com/javase/6/docs/api/java/util/Random.html#nextInt ():

Returns the next pseudorandom, uniformly distributed int value from this random number generator's sequence. The general contract of nextInt is that one int value is pseudorandomly generated and returned. All 2^32 possible int values are produced with (approximately) equal probability.

Just multiply by -1 if the value is negative

You also can use Math.random() which returns values between 0 and 1

int randomNumber = new Random().newInt(10);

This will return a random number between 0 and 9.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM