Skip to content

Instantly share code, notes, and snippets.

@motss
Last active July 23, 2019 03:40
Show Gist options
  • Save motss/cdeb9bc051e32053bca026a9ad28240f to your computer and use it in GitHub Desktop.
Save motss/cdeb9bc051e32053bca026a9ad28240f to your computer and use it in GitHub Desktop.
Determine if a given number is in range without using comparison branches and operators
/**
* This was intended for checking that an ASCII character is in range.
* But this turns out to be a function that can be used for checking if a number is in range too.
*
* Assuming, `MIN` and `MAX` are hardcoded to the code point of the character 'a' and
* the character 'z', respectively, the following equation will always return positive integers
* in the difference of the `MIN` and the `MAX`:
*
* (MAX - x) and (x - MIN) must always be positive for any of the results.
*
* When any of which produces a negative value, we know that the given number denoted by `x` is
* out of range.
*/
const MIN = 65; // 'a'
const MAX = 90; // 'z'
function inRange(a) {
const aInt = a >> 0; /** Turns Infinity, NaN into 0, which makes no changes to valid numbers */
const lowerBound = aInt - MIN;
const upperBound = MAX - aInt;
const lowerBoundSign = lowerBound >>> 31; /** Get the sign bit of the lower bound result */
const upperBoundSign = upperBound >>> 31; /** Get the sign bit of the upper bound result */
// Expected output (left) which technically is an inverse of an OR truth table (right)
// | | R | | | OR |
// | 0 | 0 | 1 | | 0 | 0 | 0 |
// | 0 | 1 | 0 | | 0 | 1 | 1 |
// | 1 | 0 | 0 | | 1 | 0 | 1 |
// | 1 | 1 | 0 | | 1 | 1 | 1 |
return !(lowerBoundSign | upperBoundSign);
};
[-65, -1, 0, 64, 65, 70, 74, 80, 85, 90, 91, Infinity, NaN].filter(n => inRange(n));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment