Could FloatingPoint random(in: Range, using:) use highest instead of lowest bits?

Hi!

Are there any particular reason why the .random(in: using:) for floating point types are using the lowest rather than the highest bits?

AFAIK for most pseudorandom generators, it is the case that lower bits have lower quality (are less "random"), so the higher bits should be preferred (because they'd often be more "random").

I'm no expert, so please correct me if I'm wrong.

But if it is a valid assumption, I wonder if instead of masking out and using the lowest bits, as in the current implementation:

      let significandCount = Self.significandBitCount + 1
      let maxSignificand: Self.RawSignificand = 1 << significandCount
      // Rather than use .next(upperBound:), which has to work with arbitrary
      // upper bounds, and therefore does extra work to avoid bias, we can take
      // a shortcut because we know that maxSignificand is a power of two.
      rand = generator.next() & (maxSignificand - 1)

it would be better to shift down and use the highest bits, like this:

      let shifts = Self.RawSignificand.bitWidth - (Self.significandBitCount + 1)
      rand = generator.next() >> shifts

?

cc @palimondo @scanon

1 Like

Any even vaguely decent PRNG these days should have reasonable quality in all the bits. Some very high-perf RNGs (xoroshiro, IIRC) have limited linearity in the low bits, but some others (e.g. PCG) do not. In the system RNG used in Swift by default, this is a complete non-issue.

Either way, the difference is extremely slight, and only effects the lowest-order bits of the resulting floating-point number, so it's much less significant than e.g. computing a random bool with x & 1 instead of x < 0.

Personally, I would argue that if your randomness source has known weak bits, you should be masking those out of the stream before using it to generate random numbers, but that's probably a losing battle. So yes, I think there's a very small improvement to be had here, which in a perfect world would be unnecessary.

4 Likes