Typescript Math Toolkit Random Integer In Range

I just finished the V1.0 math package for the Typescript Math Toolkit.  The final holdout was the random integer in range class and a supporting (seeded) RNG.  The problem of computing a pseudo-random integer in a range [i1,  i2] comes up often in front-end programming.  The standard approach is a trivial one-liner,

i1 + Math.round(Math.random()*(i2-i1))

Although the supplied RNG is linear congruential, it is generally suitable for interactive applications.  There is, however, a bias problem with the above code.  For example, consider the interval [0,3].  Possible integers are 0, 1, 2, and 3.  Based on the way rounding is implemented, numbers in the interval [0.5,1.5) get mapped to 1.  Numbers in [1.5, 2.5) get mapped to 2.  Numbers in [0,0.5) are mapped to 0.  Numbers in (2.5,3) are mapped to 3.  There is a higher probability of a pseudo-random selection getting mapped to 1 or 2 than 0 or 3 since the interval width is greater.  In fact, we would expect over the long term that the bias is about a factor of two!

Here is a code segment to illustrate that observation.

let i: number;
let x: number;
let i1: number = 0;
let i2: number = 3;
let f0: number = 0;
let f1: number = 1;

for (i=0; i<10000; ++i)
{
  x = i1 + Math.round(Math.random()*(i2-i1));

  if (x == 0 || x == 3)
    f0++;
  else
    f1++;
}

let ratio1: number = f1/f0;
console.log( "0 & 3 frequency: ", f0 );
console.log( "1 & 2 frequency: ", f1 );
console.log( "ratio: ", ratio1 );

// Typescript Math Toolkit
let generator: RandomIntInRange = new RandomIntInRange(0, 3);
f0 = 0;
f1 = 0;

for (i=0; i<10000; ++i)
{
  x = generator.generate();

  if (x == 0 || x == 3)
    f0++;
  else
    f1++;
}

let ratio2: number = f1/f0;
console.log( "0 & 3 frequency: ", f0 );
console.log( "1 & 2 frequency: ", f1 );
console.log( "ratio: ", ratio2);

When the ratios are logged, ratio1 is close to 2.0 and ratio2 is close to 1.0 .  The Typescript Math Toolkit class automatically compensates for the bias inherent in the naive implementation.  You can see this in action in the Typescript Programming Tests repo and get a complimentary copy of the alpha version of the RandomIntInRange class along with the seeded Park-Miller RNG.  The latter is useful for consistent testing as a single seed value generates the same sequence.

Comments are closed.