Skip to content

Normalise

Module Numbers.Normalise

Normalisation converts values from some scale to a consistent scalar 0..1 range. It is very helpful to have all your logic based on this same scale rather than working with absolute units like pixels, angles etc.

For simple normalisation, some sense of the input range of values is needed: a minimum and maximum. For example, although an analog input value might theoretically be in the range of 0..1023, perhaps we’ve empirically discovered that the usable range is actually 0..400. This would constitute the range of the value.

Arrays

If you have all the data in advance, it’s easy enough to ‘perfectly’ normalise, because the smallest and largest value can be determined. Normalise.array(source) returns a normalised copy of source, such that the smallest value becomes 0 and the largest value 1.

import { Normalise } from 'https://unpkg.com/ixfx/dist/numbers.js';
Normalise.array([100,20,0,50]); // [1, 0.2, 0, 0.5]

A range can be forced by passing in a min and max value. In the example below, we force a range of 0..50. Values outside of the range will be ‘clipped’.

import { Normalise } from 'https://unpkg.com/ixfx/dist/numbers.js';
Normalise.array([100,20,0,50], 0, 50); // [1, 0.4, 0, 1]

Stream

We don’t always have a complete data set to normalise. Sometimes we have streaming values, and it might be that we never know the range of the data. Normalise.stream creates a normalise function which automatically adapts as values are processed.

import { Normalise } from 'https://unpkg.com/ixfx/dist/numbers.js';
// Initialise a streaming normaliser
const n = Normalise.stream();
// Yields 1, because 5 is the highest seen
n(5);
// Yields 1, because now 10 is the highest seen
n(10);
// Yields 0, because it's so far the lowest seen
n(5);
// Yields 0.5, becaause it's in the middle of the range seen thus far
n(7.5);
// Yields 1, because now it's the largest seen
n(11);

It should be clear from the examples that different input values may produce the same output value, depending on what has been seen before. For example, an input of 5 yields 1 if 5 is the highest value, but 5 yields 0.05 if 100 is the highest value. It’s good to remember then that normalised values aren’t necessarily comparable to each other.

It’s possible to ‘prime’ the normalisation if you know in advance what range of values to expect. If a value exceeds the range, the range is updated to encompass the new minimum or maximum.

import { Normalise } from 'https://unpkg.com/ixfx/dist/numbers.js';
// Initialise normaliser, assuming range of 0-10
const n = Normalise.stream(0, 10);
// Yields 0.5, because it's in the middle of the primed range
n(5);
// Yields 1, with 11 now treated as the max
n(11);

See also