I am looking for a way to generate bitmasks of varying widths, from 0 to 32 bits, in JavaScript. This has to work for all widths from 0 through 32, so that:
bitmask(0)
should return 0
in binary (decimal 0
);bitmask(2)
should return 11
in binary (decimal 3
);bitmask(5)
should return 11111
in binary (decimal 31
);bitmask(32)
should return 11111111111111111111111111111111
in binary (decimal 4294967295
[uint32] or -1
[int32]).The expression (1 << width) - 1
works for widths from 0 to 30.
Is there a simple expression (preferably without if/else branching) that can accomplish this for the full range of inputs (0-32)?
This test code illustrates how my current approach fails for 31 and 32:
function bitmask(width) {
return (1 << width) - 1;
}
function test(width){
var result = bitmask(width).toString(2);
console.log(width,
result,
result.replace(/[^1]/g,'').length === width? 'Ok': 'Fail');
}
test(0);
test(1);
test(5);
test(17);
test(30);
test(31); // fails
test(32); // fails
In JavaScript, bitwise operators work treating the operands as 32bit integers. From the MDN Documentation:
The operands of all bitwise operators are converted to signed 32-bit integers in two's complement format.
This means that 31 bits are used to represent the actual number, and one bit (the leftmost) is used to represent the sign. So trying to do something like x << 31
will cause an overflow and produce a wrong result.
You should consider using a different method, like Math.pow()
, to obtain longer bitmasks (and higher values). Here's an example:
function bitmask(width) {
return Math.pow(2, width) - 1;
}
Now, given that JavaScript uses the IEEE Standard 754 floating point representation, there will also be limits with this function: it will only work for bitmasks shorther than 54 bits. For example, bitmask(54)
produces an integer one unit higher than the correct one, bitmask(55)
produces an integer three units higher than the correct one, and so on, the error grows up with the bitmask width.
Also, note that, even though this function can produce bitmasks longer than 31 bits, those bitmasks still cannot be used with bitwise operators, for the reason described above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With