Bitwise Operators and int32 Coercion

AND/OR/XOR/NOT and Shifts All Coerce Operands to Signed 32-Bit Integers

Bitwise Operators and int32 Coercion

JavaScript's bitwise operators silently convert their operands to signed 32-bit integers, which enables fast tricks like flooring with |0 but produces surprising results for large numbers — BigInt is the safe escape hatch.

5 min read Level 2/5 #dsa#bits#bitwise
What you'll learn
  • Apply AND, OR, XOR, NOT, and shift operators to solve common bit problems
  • Explain why JS bitwise ops coerce to int32 and the implications for values above 2^31
  • Use BigInt bitwise operators for integers that exceed the 32-bit range

JavaScript numbers are 64-bit IEEE 754 floats, but every bitwise operator (&, |, ^, ~, <<, >>, >>>) first converts both operands to a signed 32-bit integer, performs the operation in 32-bit space, then returns the result as a regular JS number. This is fast and enables some clever tricks — but it silently truncates values outside the range -2,147,483,648 to 2,147,483,647.

The Six Operators

OperatorNameEffect on bits
a & bAND1 only where both are 1
a | bOR1 where either is 1
a ^ bXOR1 where bits differ
~aNOTflip all bits (equals -(a+1))
a << nLeft shiftmultiply by 2^n (mod 32)
a >> nRight shiftdivide by 2^n, preserve sign
a >>> nUnsigned right shiftdivide by 2^n, fill with 0
console.log(5 & 3);   // 1   (0101 & 0011 = 0001)
console.log(5 | 3);   // 7   (0101 | 0011 = 0111)
console.log(5 ^ 3);   // 6   (0101 ^ 0011 = 0110)
console.log(~5);      // -6  (flip bits of 0…0101 => 1…1010, two's complement = -6)
console.log(1 << 4);  // 16
console.log(16 >> 2); // 4

The int32 Coercion Gotcha

// x | 0 is a popular floor-to-integer trick
console.log(3.9 | 0);          // 3  — works fine
console.log(2 ** 31 | 0);      // -2147483648  — overflows to most negative int32!
console.log(2 ** 32 + 1 | 0);  // 1  — upper 32 bits are discarded

Any value whose absolute value exceeds 2^31 - 1 will be silently mangled by a bitwise op. If you need to bit-manipulate large integers, use BigInt.

BigInt Bitwise Operations

BigInt literals end with n. All bitwise operators work on BigInt operands, but you cannot mix BigInt and Number in the same expression.

const big = 2n ** 40n;          // 1099511627776n
console.log(big & 0xFFn);       // 0n — low 8 bits of a 40-bit number
console.log(big | 1n);          // 1099511627777n — set bit 0
console.log(big >> 8n);         // 4294967296n (shift amount must also be BigInt)

Note that >>> (unsigned right shift) is not defined for BigInt — it would be meaningless because BigInt has arbitrary precision and no fixed sign bit.

Common Tricks

// Fast integer floor (safe only for |x| < 2^31)
const floor = x => x | 0;

// Swap without a temp variable
let a = 7, b = 3;
a ^= b; b ^= a; a ^= b;
console.log(a, b); // 3 7

// Check if n is a power of two
const isPow2 = n => n > 0 && (n & (n - 1)) === 0;
console.log(isPow2(64));  // true
console.log(isPow2(100)); // false

Up Next

Build on these fundamentals to set, clear, toggle, and test individual bits using bit masks.

Bit Masks →