DEV Community

loading...

Rigging Math.random()

2spacemilk profile image Mark Harless ・2 min read

Math.random() returns a random decimal number between 0 and 1 (1 being exlusive). So 0, 0.5 and 0.99999 are all valid returns for this JavaScript function.

But what the hell can we do with that?

Pro tip: Scroll to the bottom where I created an NPM package to handle many JavaScript random number generation for you to use ;)

Well, here's one advanced example! What if we can pass in an array of arrays to a function containing data and the percent chance of it being selected against all of the other elements in the array? Sounds a bit confusing but let's take a look at an example array argument:

const arr = [
  ["Hoyt", 15],
  ["Kassad", 30],
  ["Silenus", 45],
  ["Weintraub", 10],
]
Enter fullscreen mode Exit fullscreen mode

As you can see above, there are strings that we want to use to represent our data to be randomly selected. You can replace this with a number, another array, an object, etc. And the second element in the index is a number representing the percent chance of that array to be selected.

chance(arr) {
    const total = arr.reduce((acc, curr) => acc + curr[1], 0);
    if (total !== 100) throw new Error("sum of percentages must equal 100");

    const sorted = arr.sort((a, b) => a[1] - b[1]);

    const percent = to(100);
    let sum = 0;

    for (let j = 0; j < sorted.length; j++) {
      sum += sorted[j][1];
      if (sum >= percent) {
        return sorted[j][0]
      }
    }
  }
}

to(num) {
  return Math.round(Math.ceil(this.randomizer() * num + (num > 0 ? 1 : 0)) - 1)
  }
Enter fullscreen mode Exit fullscreen mode

In the code above we've made two functions. chance() is the one we've been talking about but it also uses a function called to(). Looking at chance() the first section checks to see if the sum of the numbers in the arrays equals 100. If it's any more or any less we throw an error.

Then we create a constant called sorted which is all of the arrays sorted by the smallest percent chance of happening to largest. We also create sum and set it equal to 0.

From there we create a random percent value between 1 and 100 (inclusive) using our second function to().

Lastly, we add the percentage chance of the first element to our sum variable. We create a standard for loop to go through each array. If sum is less than percent, we repeat the loop by adding the next percent chance to sum. We repeat this until sum is equal to or greater than percent. And that, ladies and gentlemen, is how you rig JavaScript randomization.

I've created a little side project to handle various number randomization methods on npm called totally-random. It can create a random number between two numbers, a random number up to a positive number or down to a negative number, random strings (alpha, numeric and alphanumeric) of different lengths, random colors (hex, rgb, rgba, hsl and hsla), and much, much more!

It is open source so feel free to contribute if you find this package to be of any use to you :)

Discussion

pic
Editor guide