Skip to content

Random

The Module Random module has a notion of a RandomSource. This just a function that returns a random value, matching the in-build Math.random semantics. This means that Math.random can always be used as a RandomSource for any ixfx function.

For example:

import { Random } from 'https://unpkg.com/ixfx';
// Create source
const source = Random.integerSource();
// Generate a value
source(); // Returns a random value

Why the two-step process? It can sometimes be handy to ‘bake in’ some settings for random number generation in one place. For example, if you were generating random numbers within a particular range, you don’t want to have to repeat the range settings all through your code.

const source = Random.integerSource(10); // Random number 0..9
const source = Random.integerSource({ min: -5, max: 20 }) // Random numbert -5...19

If you for sure don’t need to reuse the number generator, you can use the following syntax. Note the extra () after the function parameters. This immediately invokes the function.

Random.integerSource(10)(); // Yields a random value

We also need the RandomSource approach because sometimes we need to pass the random generation to some other function. For example, if we want get a random element from an array:

// Create weighted random number generator
const source = Random.gaussianSource();
// The array of data
const v = [`blue`, `red`, `orange`];
// Returns a random element from array
Random.randomElement(v, source);

Since randomElement can take any RandomSource, we can customise how it picks a random element by giving it a different source.

Functions which create RandomSources include:

Normally random values are evenly distributed - where no part of the range is privileged. This is akin to classic noise or static, it’s pretty much completely random. This is like rolling a dice. Each roll there’s a completely even chance of getting any side.

But there are times where you want to skew this distribution. You still want randomness, but you want more values from the middle of a range, for example. This would be akin to adding a bit of weight to one side of the dice. It will still give different values, but there’s a higher chance of some numbers depending on the position of the weight.

Random.gaussianSource produces gaussian-distributed random values (ie. more likely to be values from the middle of the range)

// repl-pad
import { Random } from 'https://unpkg.com/ixfx';
const source = Random.gaussianSource();
source(); // Generate value

Modulation.weightedSource is from the Modulation module, and can produce weighted random values using an easing curve

import { Random } from 'https://unpkg.com/ixfx';
const source = Random.weightedSource({ easing: `bell` }); // Create the source using the 'bell' easing curve
source(); // Generate a random value

‘Seeded’ random generators allow you to create a predictable series of random values given a seed value. The ‘seed’ value essentially becomes a key to a stream of random values which will be the same each time your code runs — assuming the seed value is the same.

This technique is often used in procedural map generation such as in Minecraft. A player’s world is generated randomly based on a single seed value. If it turns out that seed produces an interesting map, players can share that seed with others and in principle their copy of Minecraft will generate the same world when the seed is given as input.

It’s likewise used in generative art where the artist wants to include randomness, but still have authorial control of finding the ‘right’ randomness.

The simplest is using the ‘mulberr32’ algorithm with Random.mulberrySource:

import { Random } from 'https://unpkg.com/ixfx';
// Create the source
const source = Random.mulberrySource({ seed: 10 });
// Each call to source() generates a predicatable random number
source();

Alternatives algorithms

There are a few functions for producing random millisecond values. They are mostly for making your code more literate, and since they return millisecond values, can be plugged directly into something like setTimeout.

secondsMs(5000); // Generate random milliseconds from 0..5000
minutesMs(1); // Generate random milliseconds corresponding to 0...60_1000
setTimeout(() => {
// Do something after a random wait of 1..5 minutes
}, minutesMs({ min: 1, max: 5 }));

See:

Random.calculateNonZero uses a RandomSource, but skips values which are zero:

calculateNonZero(Math.random); // something other than 0

Random.chance returns one value or another with a given chance:

// 90% of the time will return 110, 10% of the time will return 100.
chance(0.9, 100, 110);

Tip: Instead of fixed values for chance or the two values, you can use functions to dynamically determine it.

Random.integerUniqueGen returns a generator over unique integer values.

for (const v of integerUniqueGen(10)) {
// Outputs a random sequence of 0..9
}

Random.shortGuid produces a short ‘globally unique id’. Essentially, a random six-digit string that’s unlikely to collide with another. You can use Random.string to produce a random string of a given number of characters.

// Whole module
import * as Random from "@ixfx/random.js"
// Single function
import { bipolar } from "@ixfx/random.js"
// And within your HTML's <HEAD> </HEAD> block:
<script type="importmap">{ "imports": { "@ixfx":"/ixfx/core.js", "@ixfx/": "/ixfx/" } }</script>