BIT-101
Bill Gates touched my MacBook Pro
I’m going to do a series of short articles, labeled FOTD
- Function Of The Day. These might be math functions, drawing functions, PRNG functions, color functions, etc. Mostly these will be useful for visual or creative coders.
Each post will be short. Just a single function, how it works, what it might be used for, and maybe an example or two. No particular schedule for these. As the mood strikes me. But between the two main libraries I’ve curated, blcairo
and bitlib
, I have close to 1000 functions, so there should be no shortage of material. Maybe worth noting that I’ll usually be using some kind of pseudocode for all the examples.
Today’s function is norm
. This takes in three parameters: value
, min
and max
. It returns a number between 0.0 and 1.0 based on where value
falls between min
and max
. Actually, if value
is less than min
it will return a negative number, and if value
is greater than max
it will return something larger than 1.0. But in most use cases, the min/max range will be contrived so that value
fits into it cleanly.
In pseudocode, norm
looks like this:
function norm(value, min, max) {
return (value - min) / (max - min)
}
The max - min
part gets the range between those two values. Subtracting min
from value
puts value into that range (if it can be put into that range). Dividing the two give you zero if value
equals min
, one if value
equals max
and somewhere between if value
is between the two.
There’s one use for norm
that’s immediately useful. I often use Perlin or Simplex noise to generate patterns or what have you. In some libraries these noise functions return a value between 0.0 and 1.0, which is already normalized. But in most, they return a value from -1.0 to 1.0. I have color functions that take values for channels in floats between 0.0 and 1.0, so I need to convert between the two.
I could say:
colorValue = (noise + 1) / 2
// or...
colorValue = noise / 2 + 0.5
Adding one moves the noise range to 0.0 to 2.0. Dividing by two puts it into a normalized range. The second version does something similar.
With norm
I can say:
colorValue = norm(noise, -1, 1)
It’s a couple more characters, but for me, less of a cognitive load. There’s no math involved, I’m just mapping from -1, 1 to 0, 1.
Norm is often used as just one step in a calculation. Once you have the norm, you might want to do some further calculations with that value.
Say I was using atan2
to calculate angles between two points, like a center point and another pointer. This gives you a number from -PI to PI. You can use norm
to normalize that to a 0, 1 range. Multiply that value by the width of the canvas, in my case 400, and now you can use that to draw a kind of gauge showing the value. Like so:
angle = atan2(y - centerY, x - centerX)
value = norm(angle, -PI, PI) * 400
moveto(value, 0)
lineto(value, 20)
Now this might seem a little bit contrived, because honestly it is. The fact is, I don’t use norm
by its own all the much other than the noise example above. But it goes well inside other more complex functions, some of which we’ll visit later.
I did a video on this function on my Coding Math Youtube channel. View it here: Coding Math Mini #1, Normalization
Comments? Best way to shout at me is on Mastodon