0

I'm trying to write a random digit generator that does a better job than Math.random.

However, each time I run the test I notice that digits 6-9 occur less frequently than digits 1-5. I realize that this could randomly happen, but it happens every time I've tried it. Odds are, there's just something wrong with the getRandomDigits function.

How can I remove this bias?

function getRandomDigits(numDigits) {
  // Initialize an empty string to store the random digits
  let randomDigits = "";

  // Generate the specified number of random digits
  for (let i = 0; i < numDigits; i++) {
    // Generate a random number between 0 and 9 using the crypto object
    let randomNumber = window.crypto.getRandomValues(new Uint8Array(1))[0] % 10;
    // Convert the random number to a string and add it to the string of random digits
    randomDigits += randomNumber.toString();
  }

  // Return the string of random digits
  return randomDigits;
}

function testGetRandomDigits(numTests, numDigits) {
  // Initialize an object to store the number of occurrences of each digit
  let digitCounts = {};

  // Initialize the count for each digit to 0
  for (let i = 0; i <= 9; i++) {
    digitCounts[i.toString()] = 0;
  }

  // Generate the specified number of random digits and count the occurrences of each digit
  for (let i = 0; i < numTests; i++) {
    let randomDigits = getRandomDigits(numDigits);
    for (let j = 0; j < numDigits; j++) {
      let digit = randomDigits[j];
      digitCounts[digit]++;
    }
  }

  // Return the object with the counts of each digit
  return digitCounts;
}

console.log(testGetRandomDigits(1000000, 1));

Update: Here's a revised function that doesn't seem to have the bias anymore:

function getRandomDigits(numDigits) {
  // Initialize an empty string to store the random digits
  let randomDigits = "";

  // Generate the specified number of random digits
  for (let i = 0; i < numDigits; i++) {
    // Generate a random number between 0 and 9 using the crypto object
    let randomNumber = window.crypto.getRandomValues(new Uint32Array(1))[0] % 10;
    // Convert the random number to a string and add it to the string of random digits
    randomDigits += randomNumber.toString();
  }

  // Return the string of random digits
  return randomDigits;
}

function testGetRandomDigits(numTests, numDigits) {
  // Initialize an object to store the number of occurrences of each digit
  let digitCounts = {};

  // Initialize the count for each digit to 0
  for (let i = 0; i <= 9; i++) {
    digitCounts[i.toString()] = 0;
  }

  // Generate the specified number of random digits and count the occurrences of each digit
  for (let i = 0; i < numTests; i++) {
    let randomDigits = getRandomDigits(numDigits);
    for (let j = 0; j < numDigits; j++) {
      let digit = randomDigits[j];
      digitCounts[digit]++;
    }
  }

  // Return the object with the counts of each digit
  return digitCounts;
}

console.log(testGetRandomDigits(1000000, 1));
Lonnie Best
  • 9,936
  • 10
  • 57
  • 97
  • @pjs : Well, this is a javascript question and that answer is c++. It is on topic, but I'm having difficulty applying the concept from there. I'll keep reading it over and over.... – Lonnie Best Dec 16 '22 at 13:12
  • 1
    The concept of modulo bias is independent of language. – pjs Dec 16 '22 at 13:20
  • @pjs : I agree with you, I'm trying to apply the concept to my code right now. – Lonnie Best Dec 16 '22 at 13:22
  • 1
    You might be interested in [this 2019 paper](https://arxiv.org/pdf/1805.10941.pdf), which proposes an algorithm that is more efficient than the ones used by OpenBSD or Java. – pjs Dec 16 '22 at 13:33

0 Answers0