Warm tip: This article is reproduced from stackoverflow.com, please click
java random

Getting negative value from Random.nextInt using XORShift seed implementation

发布于 2020-04-05 23:37:36

From my understanding (and the javadoc), Random.nextInt should return a positive (or zero) value.

But when I use it with arguments that are power of 2, I often receive negative values. Here is my Random class:

import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

public class SavableRandom extends Random {

    private AtomicLong seed = new AtomicLong();

    /** {@inheritDoc} */
    @Override
    protected int next(int bits) {
        long newSeed = seed.get();

        newSeed ^= (newSeed << 21);
        newSeed ^= (newSeed >>> 35);
        newSeed ^= (newSeed << 4);
        seed.set(newSeed);

        return (int) (newSeed >>> (48 - bits));
    }

    /** @return the seed. */
    public long getSeed() {
        return seed.get();
    }

    /** @param seed the seed to set. */
    @Override
    public void setSeed(long seed) {
        if (this.seed != null) {
            this.seed.set(seed);
        }
    }

    public static void main(String... args) {
        Random random = new SavableRandom();
        random.setSeed(536662536331391686L);

        System.out.println(random.nextInt(13));
        System.out.println(random.nextInt(12));
        System.out.println(random.nextInt(16));
    }
}

I added a main method with a specific seed so that you could easily reproduce it (the last one returns -1).

What am I doing wrong ?

Questioner
MKL
Viewed
66
Andreas 2020-02-01 00:39

What am I doing wrong ?

Your newSeed has more than 48 bits, so (newSeed >>> (48 - bits)) has more than bits bits, meaning that you're violating the contract of next(int bits).