2

I am trying to see if I can get a proper distribution based on secure random hash. I always seem to get double for my first index. Is there something wrong that I am doing

    SecureRandom sr = new SecureRandom();

    sr.setSeed(sr.generateSeed(16));
    int zero = 0;
    int one = 0;
    int two = 0;
    int three = 0;
    int four = 0;
    int five = 0;
    int six =0;


    for (int i = 0 ; i < 100000; i++) {
        long index = sr.nextLong()%6;
        if(index == 0)
            zero++;
        else if (index == 1)
            one++;
        else if(index == 2)
            two++;
        else if(index == 3)
            three++;
        else if(index == 4)
            four++;
        else if(index == 5)
            five++;
    }
    System.out.println(zero);
    System.out.println(one);
    System.out.println(two);
    System.out.println(three);
    System.out.println(four);
    System.out.println(five);
    System.out.println(six);

Take a look at the first line of the output

Here is the output
16548
8362
8314
8175
8272
8210
Paul
  • 187
  • 1
  • 2
  • 12
  • 1
    Using % with an RNG tends to bias the RNG output. Just use `sr.nextInt(6)`. – erickson May 11 '16 at 23:28
  • @erickson, good to know. [More info](http://stackoverflow.com/questions/10984974/why-do-people-say-there-is-modulo-bias-when-using-a-random-number-generator) for the curious. – shmosel May 12 '16 at 00:06
  • @erickson, thank you. Your suggestion also works. – Paul May 12 '16 at 06:59

1 Answers1

2

You're ignoring the fact that SecureRandom.nextLong() can return negatives. So your code is only catching half of all non-zero indexes because -7 % 6 == -1, but it's catching all zero indexes because -6 % 6 == 0.

If you want all values to land between 0 and 5, just use Math.abs():

long index = Math.abs(sr.nextLong()%6);

Sample output:

16735
16510
16657
16776
16599
16723
shmosel
  • 49,289
  • 6
  • 73
  • 138