Search code examples
javascriptrandominteger-overflowrandom-seedmersenne-twister

Should this number be subtracted by 1 when implementing the Mersenne Twister?


I found this snippet online along with this Stackoverflow post which converts it into a TypeScript class.

I basically copy and pasted it verbatim (because I am not qualified to modify this sort of cryptographic code), but I noticed that VS Code has a little underline in the very last function:

/**
 * generates a random number on [0,1) with 53-bit resolution
 */
nextNumber53(): number {
  let a = this._nextInt32() >>> 5;
  let b = this._nextInt32() >>> 6;
  
  return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
}

Specifically the 9007199254740992.0

VS Code says Numeric literals with absolute values equal to 2^53 or greater are too large to be represented accurately as integers.ts(80008)

I notice that if I subtract that number by one and instead make it 9007199254740991.0, then the warning goes away. But I don't necessarily want to modify the code and break it if this is indeed a significant difference.

Basically, I am unsure, because while my intuition says that having a numerical overflow is bad, my intuition also says that I shouldn't try to fix cryptographic code that was posted in several places, as it is probably correct.

But is it? Or should this number be subtracted by one?


Solution

  • 9007199254740992 is the right value to use if you want Uniform values in [0,1), i.e. 0.0 <= x < 1.0.

    This is just the automatics going awry, this value can be accurately represented by a JavaScript Number, i.e. a 64bit float. It's just 253 and binary IEEE 754 floats have no trouble with numbers of this form (it would even be represented accurately with a 32bit float).

    Using 9007199254740991 would make the range [0,1], i.e. 0.0 <= x <= 1.0. Most libraries generate uniform values in [0,1) and other distributions are derived from that, but you are obviously free to do whatever is best for your application.

    Note that the actual chance of getting the maximum value back is 2-53 (~1e-16) so you're unlikely not actually see it in practice.