Bitwise calculator
AND masks — it keeps only the bits set in both, so ANDing with 0x0F keeps the low nibble and clears the rest. OR sets — it turns bits on without disturbing the others. XOR toggles, and applying it twice with the same value returns the original, which is why it turns up in simple ciphers and in swapping without a temporary variable.
Operations are 32-bit, which is what JavaScript bitwise operators use. Values above 2³²−1 wrap, and bits shifted past either end are discarded rather than wrapped.
Bitwise operations compare two numbers bit by bit. 12 AND 10 is 8, because only the 8-bit is set in both; OR gives 14 and XOR gives 6. Shifting left by three multiplies by eight, so 5 becomes 40. Everything here is 32-bit, the width JavaScript bitwise operators use.
How to use bitwise operations
The binary row is the one to read while learning. Bitwise operations are obvious once you can see the columns lining up: 1100 AND 1010 gives 1000 because only the leftmost column has a 1 in both. Everything else follows from that column-by-column comparison. Note that NOT operates on all 32 bits, so NOT 0 is 4294967295 rather than 1.
Four idioms cover almost all real use. To test a flag, AND with it and check the result is not zero. To set one, OR with it. To clear one, AND with its complement. To toggle one, XOR with it. Masking is the same move with several bits at once: B4 AND 0F is 04, the low nibble kept and the high one thrown away, which is how a packed field is pulled out of a byte.
Shifting is the other half of that job, and it is how the field got packed in the first place: shift a value left into position, OR it into the word, and later shift it back down and mask it off. Shifting left by n multiplies by 2ⁿ and shifting right divides and truncates, but only while nothing falls off the end. Bits pushed past either edge are discarded, so a left shift far enough gives zero.
The two right shifts differ only for negative numbers, and the difference matters. A logical right shift fills from the left with zeros, so a negative number becomes a large positive one. An arithmetic right shift copies the sign bit, preserving the sign and behaving like division by a power of two. In JavaScript >> is arithmetic and >>> is logical, and picking the wrong one is a classic source of bugs in code handling signed values.
The bug that catches everyone in the logical operations is precedence rather than logic. In C, JavaScript and most of what copied them, == binds more tightly than &, so flags & MASK == 0 is read as flags & (MASK == 0) and quietly evaluates to nothing useful. Put the AND in brackets. And & is not &&: one compares every bit of two numbers, the other stops at the first falsy operand and hands back a value rather than a bit pattern.
What people use it for
- Working out a bitmask
- Debugging flag values
- Understanding permission bits
- Packing and unpacking bit fields
- Multiplying or dividing by a power of two
- Reading a hardware register description
- Learning bitwise logic
Questions
Keeps only bits set in both values. It is how masks work: B4 AND 0F is 04.
Toggling bits. Applying it twice with the same value restores the original, which is why simple ciphers use it.
Because NOT inverts all 32 bits, giving 4294967295 rather than 1.
AND with the complement of that bit: for example AND with NOT 0x04 clears the third bit.
Usually precedence: == binds tighter than & in C and JavaScript, so flags & MASK == 0 is not what it looks like. Bracket the AND.
& compares every bit of two numbers. && is a logical test that stops at the first falsy operand and returns one of the operands.
Multiplies by two for each place shifted, as long as nothing overflows off the top. 5 shifted left by 3 is 40.
>> is arithmetic and preserves the sign; >>> is logical and fills with zeros, turning negatives into large positives.
They are discarded, not wrapped. Shifting left far enough gives zero.
Not usefully in 32-bit arithmetic; most languages take the shift count modulo 32.
It once was, meaningfully. Modern compilers make the substitution themselves, so write whichever is clearer.
Yes. JavaScript bitwise operators coerce to 32-bit signed integers, and values above that wrap.