Hello board,
so, I want to generate numbers that are random but, optionally, repeatable. What I gleaned from other threads is that the most straightforward way to do that is along these lines:
- By default, use random() to generate a value, relying on Processing/Java to supply an initial hidden and unique seed.
- Feed the value from (1) into randomSeed().
- Use random() as needed.
- Display the value from (1) to the user.
Then, if the user wants to put the Sketch into an earlier state, they can do so by replacing step (1) with manually inputting the corresponding seed. So far, so good, yes?
To implement step (1), I need to convert the output of random() into the input of randomSeed(). The one is a float, the other a… long? Being a perfectionist, I’m going to assume that it is a long, and I’m going to want that long to be “thoroughly” randomized - which is to say, for each of the 2^64 values in the long-range to occur with non-zero and equal likelihood, at least in principle. If several of those values end up putting the random generator into the same state, so be it.
Clearly, I’ll need to call random() more than once to achieve that, as there are at most 2^32 values in the float-range. My original idea was to call it twice, convert the pair of floats to a pair of integers using the Float.floatToIntBits() utility methods, and then concatenate those into a single long. That preserves all the intricacies of the stucture of a float, though, and while some of the bits in a randomly-valued float presumably have an equal likelihood of being a 0 or a 1, it may well not be safe to assume that all of them do. So that wouldn’t do the trick.
Instead, this is what I came up with:
long mRandom = 0;
for(int nFor = 0; nFor < Long.BYTES; ++nFor) {
long mChunk = (long)(random(1 << Byte.SIZE));
mRandom = (mRandom << Byte.SIZE) | mChunk;
}
Request a random number in the byte-range, truncate the non-integer portion, and OR it into the resultant long. Repeat until the long is “full” by looping and progressively left-shifting the previously-filled bits. I tried using byte as the datatype for the byte-sized chunks at first, but ran into issues with the sign-bit there, so except for the iterator, which isn’t used in the loop body, it’s all longs now.
The results look good to me, but I’d like to hear what you think and how you have done/would do this, taking into account my erring-on-the-side-of-caution-y criteria.
Cheers!