Thoroughly seeding random()

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:

  1. By default, use random() to generate a value, relying on Processing/Java to supply an initial hidden and unique seed.
  2. Feed the value from (1) into randomSeed().
  3. Use random() as needed.
  4. 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!

Hello,

Do not assume anything in programming.

All the references and resources are available here:

:)

image

Alas, as to the matter in question, the reference entry for random() disagrees with the context help in the PDE, as already mentioned in the linked thread. So as long as I treat the random generator as a black box, I have to assume at this point. What I am assuming is that if the method wants an int but accepts a long, I lose nothing by giving it a long. Vice versa, the same thing can’t be said.

I often go straight to the source for clarity:

public final void randomSeed(long seed)

It may take the browser a few seconds to actually go to the line #… my experience with Google Chrome.

Just one example.

:)

Nice, thank you for clearing that up! :slight_smile:

1 Like