-1

I wrote a demo to test java.util.Random and I want to produce a repeating list of the same 5 numbers, but I get the same value when set different seeds.In my program, seeds range from 0 to 4. As far as I know, different seeds produce different values and the same seed get the same value. So I think the result will be a repeating list of the same 5 numbers. But the actual values output are all the same. What's wrong with my code? Could anyone tell me?

import java.util.Random;

public class Main {
    public Main() {
    }

    public static void main(String[] args) {
        for (int i = 0 ; i <= 255; i++)
        {
            String hex = Integer.toHexString(randInt(0, 255, i % 5));
            System.out.println(hex);
        }
    }
    private static Random rand = new Random();
    public static int randInt(int min, int max, long seed) {
        rand.setSeed(seed);
        System.out.println("seed:" + seed);
        int randomNum = rand.nextInt((max - min) + 1) + min;
        return randomNum;
    }
}

The result is :

seed:0
bb
seed:1
bb
seed:2
bb
seed:3
bb
seed:4
bb
seed:0
bb
seed:1
bb
seed:2
bb
seed:3
bb
seed:4
bb
seed:0
bb
seed:1
bb
seed:2
bb
seed:3
bb
seed:4
bb
seed:0
bb
seed:1
...
...
...
dragonfly
  • 1,151
  • 14
  • 35
  • The more probable answer is that there is a bug in your code. You should isolate the different parts and test whether you do what you think you're doing. – Silverclaw Jul 14 '16 at 13:58
  • 4
    not sure what you want to achieve, but it is not how you use Random. You set seed once, and then take numbers from it. – mlecz Jul 14 '16 at 14:03
  • Try just doing `int randomNum = rand.nextInt(max) + min;` It's also worth noting that each time you change the seed it resets, so you will get a repeating list of the same 5 numbers in this case. – Andrew Jul 14 '16 at 14:04
  • I have printed the seed to console, You can take a look at it, or you can paste the code to IDE and run it. – dragonfly Jul 14 '16 at 14:04
  • No thanks, you can do the debugging yourself. – Silverclaw Jul 14 '16 at 14:18
  • (max - min) + 1 equals 256 which gives problems, but if you put 255 it works fine. – FedeWar Jul 14 '16 at 14:25
  • It works even with 257, for some reason you can't use 256. – FedeWar Jul 14 '16 at 14:26

2 Answers2

3

As far as I know, different seeds produce different values

This is incorrect, different seeds may produce different values, they can also produce the same values.

There are 2^64 possible seeds and rand.nextInt(256) can only return 256 different values so many of the seeds must return the same value.

Also the setSeed javadoc states

The implementation of setSeed by class Random happens to use only 48 bits of the given seed

So if your seed differs in only the ignored bits all of the values will be the same.

Alex - GlassEditor.com
  • 14,957
  • 5
  • 49
  • 49
  • "different seeds produce different values" is incorrect. Does the same seed produce the same value on different platforms and devices? – dragonfly Jul 15 '16 at 11:36
  • @dragonfly Yes, unless there is a bug in the platform's `Random` implementation. The javadoc requires the same seed to produce the same values in all Java implementations. Note that some of the methods like `nextFloat` and `nextDouble` have changed over time and may change again in the future, so you might not get the same values if you use different Java versions. – Alex - GlassEditor.com Jul 15 '16 at 12:26
  • 1
    @dragonfly Also It looks like `Random` does not use `strictfp` so the methods that use floating point numbers may generate slightly different results across platforms. – Alex - GlassEditor.com Jul 15 '16 at 12:40
0

I have found this implementation on grepcode, there's an if statement to detect if n is a power of 2. If n (i.e. the bound) is a power of 2 (int)((n * (long)next(31)) >> 31); is used.

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

I don't know if this implementation is used in your JDK but this suggests that power of 2 bounds are treated differently.

The algorithm treats the case where n is a power of two specially: it returns the correct number of high-order bits from the underlying pseudo-random number generator. In the absence of special treatment, the correct number of low-order bits would be returned. Linear congruential pseudo-random number generators such as the one implemented by this class are known to have short periods in the sequence of values of their low-order bits. Thus, this special case greatly increases the length of the sequence of values returned by successive calls to this method if n is a small power of two.

FedeWar
  • 537
  • 1
  • 7
  • 17