Randomizing Program Execution with Random Number Generators

Different ways to use Math.random() and its equivalents

Alex Bainter
5 min readMay 31, 2019

--

Utilizing randomness in software isn’t something I’ve had to do for professional work, but it’s the basis of most of my creative software projects. Most notably, I make generative music hosted on Generative.fm. This involves a great deal of randomization, such as scheduling events at random times or making random selections of notes to play. Even my personal site has a background which slowly changes to a random color every few seconds.

When I first started creative coding projects, it wasn’t obvious to me how I could randomize my programs. I knew about Math.random(), but I wasn’t sure how to apply it to all my use cases. Now these techniques are second nature, and I wanted to share some tips for anyone getting started with creative coding or generative art.

I’ll be using JavaScript throughout this post, but these techniques work with any programming language or library which has a random number generator like Math.random().

Math.random()

In JavaScript, Math.random() returns a pseudo-random number between 0 (inclusive, meaning it might return 0) and 1 (exclusive, meaning it can’t actually return 1). Run the embedded CodePen below to see numbers returned from Math.random():

This is nice if you need a number between 0 and 1, but what about other applications of randomness? What if you need a random number between 2 and 7? What if you want some part of your program to randomly execute about 25% of the time? You can do this and more with Math.random().

Random Number Between 0 and <Max>

Getting a random number between 0 and some other number is simple. Just multiply the maximum desired number by Math.random(), like so:

function getRandomUpTo(max){
return Math.random() * max;
}

Since Math.random() returns a value between 0 (inclusive) and 1 (exclusive), this function will return a value between 0 (inclusive) and max (exclusive).

Random Number Between <Min> and <Max>

Now let’s write a function which returns a value within a range we specify.

Our function will take two parameters, min and max, and return a random number between those two values.

function getRandomBetween(min, max) {
// TODO: return a value between min and max
}

Since min is the smallest number which should be returned by this function, let’s start by simply returning min:

function getRandomBetween(min, max) {
return min; // TODO: make this value between min and max
}

This satisfies our condition that this function should return a value which is greater than or equal to min. Now we can add a random, positive number to min to get our desired output.

What numbers can we add to min to finish our function? The smallest value we can add is 0, since adding a negative number would reduce the output below min. The largest value we can add is the difference between max and min, or max — min. For example, if we want a value between 2 and 7 and our function returns 2 + <some number>, the most we can add to keep the summation within our range is 5 (or 7 - 2). So we need a random number between 0 and max — min. And hey, we just wrote a function to do that!

function getRandomBetween(min, max) {
return min + getRandomUpTo(max - min);
}

Or, in case you want to see the full arithmetic:

function getRandomBetween(min, max) {
return min + Math.random() * (max - min);
}

Remember, because Math.random() will never return 1, this function will never return max!

Random Integer Between <Min> and <Max>

To get a random integer, we can use either Math.ceil() or Math.floor() to round our random numbers up or down to the nearest integer, respectively. Be careful to choose the correct method for your use case! For example, Math.floor(Math.random()) will always return 0, but Math.ceil(Math.random()) will almost always return 1. Likewise, let’s say you wrap a call to our previous function getRandomBetween(min, max) with Math.ceil, like this:

Math.ceil(getRandomBetween(0, 5));

This code snippet will return a value between 0 (exclusive) and 5 (inclusive); the inclusivity of the edges flipped! For this reason, I prefer to use Math.floor() to get random integers, as the result will behave the same way as Math.random() itself:

function getRandomIntegerBetween(min, max) {
return Math.floor(getRandomBetween(min, max));
}

This function returns an integer between min (inclusive) and max (exclusive), so the inclusivity of the edges matches the behavior of Math.random(), which returns a value between 0 (inclusive) and 1 (exclusive).

Random Element of Array

Now that we can get random integers, it’s easy to get a random element from an array. We just need a random integer between 0 and the array’s length (but not including its length!). I’ll use the first function we defined, getRandomUpTo(max):

function getRandomFromArray(arr) {
return arr[Math.floor(getRandomUpTo(arr.length)];
}

Probabilities

Let’s say you have a branch of code which you only want to execute 25% of the time. Since the output of Math.random() can be any number between 0 and 1, we know the value it returns will be less than 0.25 roughly 25% of the time. Just call Math.random() and check that the output is less than the percentage you want, in this case 0.25:

if (Math.random() < 0.25) {
// do something
}

We could even write a function for this, which I’ll call p:

function p(probability) {
return Math.random() < probability;
}
if (p(0.25)){
// do something
}

To get pedantic for a moment, it’s most appropriate to use < and not since the return value of Math.random() is inclusive of 0 and exclusive of 1. This means the expression Math.random() ≤ 0 could actually be true, albeit very infrequently. Still, I’ll argue there should be exactly 0% chance our p function returns true when it’s called with 0. It doesn’t really matter in practice, but it’s worth mentioning anyway so I can feel smart.

In addition to control flow, I use this technique to grab a random sampling of elements from an array. For example, this snippet will return about half of the elements of an array, chosen at random:

const elements = someArray.filter(() => p(0.5));

Keep in mind this could return 0 elements or it could return all the elements, and everything in between. But if we run this code repeatedly, on average it will return about half the elements in the array.

These techniques provide everything I need to randomize my creative software projects. When I first started, I didn’t understand all the different ways Math.random() could be used to do what I want, but I’ve since found it fulfills all my randomization needs. I’ll bet it covers yours too.

Thank you so much for reading.

You can follow me on Twitter or subscribe to my newsletter to receive paywall-free links to my Medium posts. If you’re not a paid Medium member, reading via these links won’t count against your monthly limit.

Check out Generative.fm if you like ambient music or want to hear music which never ends nor repeats itself. Many users (myself included) find this type of music helps them concentrate while they work, study, or read, but also during activities like relaxing or meditating. The site is completely free and doesn’t feature advertising (unless you count my PayPal and Patreon links on the about page). And, it’s open source.

--

--

Alex Bainter

A web developer creating audio/visual experiences both digital and not. Currently making generative music at Generative.fm.