Reputation: 8815
I'm trying to shuffle an array of integer as per below,
and from http://en.wikipedia.org/wiki/Fisher-Yates_shuffle,
"An additional problem occurs when the Fisher–Yates shuffle is used with a pseudorandom number generator or PRNG: as the sequence of numbers output by such a generator is entirely determined by its internal state at the start of a sequence, a shuffle driven by such a generator cannot possibly produce more distinct permutations than the generator has distinct possible states. ... "
What's the easiest way to fill the seed byte array ? i.e.
byte[] seed = new byte[2048]; // fill the seed byte with random stuff, what's the easiest way ? SecureRandom secureRandom = new SecureRandom(seed);
Code:
/**
* http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
*
* To shuffle an array a of n elements (indices 0..n-1):
* for i from n − 1 downto 1 do
* j ← random integer with 0 ≤ j ≤ i
* exchange a[j] and a[i]
*/
public int[] shuffle (int[] inSet ) {
int [] returnSet = Arrays.copyOf(inSet, inSet.length);
for( int i = inSet.length-1; i > 0; i-- ) {
// j ← random integer with 0 ≤ j ≤ i
int j = secureRandom.nextInt(i+1);
// swap returnSet[i] and returnSet[j]
int temp = returnSet[i];
returnSet[i] = returnSet[j];
returnSet[j] = temp;
}
return returnSet;
}
Upvotes: 1
Views: 733
Reputation: 26882
Here is a good article: "A Java Programmer’s Guide to Random Numbers"
Basically, a) You don't want to use java.util.Random
as it is exhibits periodic behavior (bad randomness), b) SecureRandom
is a big improvement over java.util.Random
, but depending on the number of elements you want to shuffle, the degrees of freedom it provides might be too small (see this section for details). Also another problem is that SecureRandom
is quite slow. If you have performance problems, you can follow the link above for alternative PRNGs that are faster than SecureRandom
.
Upvotes: 3
Reputation: 291
I think that the size of the array is not so important as its content. One common practise is to create the seed on current time. You can also ask the user (if possible) to apply some random keyboard or mouse input. I've noticed this technique in password managers.
Everything depends on your needs. I bet that quite sensible way would be to take System.currentTimeMillis() (optionally you can play with it by joining it multiple times or hash it).
Upvotes: 0