What's the most elegant way to cap a number to a segment?
Let's say x
, a
and b
are numbers. I need to limit x
to the bounds of the segment [a, b]
.
In other words, I need a clamp function:
clamp(x) = max( a, min(x, b) )
Can anybody come up with a more readable version of this?
Solution 1:
The way you do it is pretty standard. You can define a utility clamp
function:
/**
* Returns a number whose value is limited to the given range.
*
* Example: limit the output of this computation to between 0 and 255
* (x * 255).clamp(0, 255)
*
* @param {Number} min The lower boundary of the output range
* @param {Number} max The upper boundary of the output range
* @returns A number in the range [min, max]
* @type Number
*/
Number.prototype.clamp = function(min, max) {
return Math.min(Math.max(this, min), max);
};
(Although extending language built-ins is generally frowned upon)
Solution 2:
a less "Math" oriented approach, but should also work, this way, the <
/ >
test is exposed (maybe more understandable than minimaxing) but it really depends on what you mean by "readable"
function clamp(num, min, max) {
return num <= min
? min
: num >= max
? max
: num
}
Solution 3:
There's a proposal to add an addition to the built-in Math
object to do this:
Math.clamp(x, lower, upper)
But note that as of today, it's a Stage 1 proposal. Until it gets widely supported (which is not guaranteed), you can use a polyfill.
Solution 4:
A simple way would be to use
Math.max(min, Math.min(number, max));
and you can obviously define a function that wraps this:
function clamp(number, min, max) {
return Math.max(min, Math.min(number, max));
}
Originally this answer also added the function above to the global Math
object, but that's a relic from a bygone era so it has been removed (thanks @Aurelio for the suggestion)