Understanding Bits and Binary

A bit (binary digit) is the fundamental unit of information in computing. It can hold one of two values: 0 or 1. When JavaScript performs bitwise operations, it converts numbers to 32-bit signed integers.

💡

Binary Representation

Here's how decimal numbers are represented in binary:

Decimal 5  = Binary 00000000000000000000000000000101
Decimal 10 = Binary 00000000000000000000000000001010
Decimal -1 = Binary 11111111111111111111111111111111

Note: JavaScript uses Two's Complement for negative numbers.

Complete Bitwise Operators Reference

Operator Symbol Description Example Result
AND & Returns 1 if both bits are 1 5 & 3 1
OR | Returns 1 if either bit is 1 5 | 3 7
XOR ^ Returns 1 if bits are different 5 ^ 3 6
NOT ~ Inverts all bits ~5 -6
Left Shift << Shifts bits left, fills with 0s 5 << 1 10
Right Shift >> Shifts bits right, preserves sign 5 >> 1 2
Zero-fill Right Shift >>> Shifts bits right, fills with 0s -5 >>> 1 2147483645

Detailed Examples with Visual Breakdown

&

Bitwise AND (&)

The AND operator compares each bit and returns 1 only if both bits are 1.

// Example: 12 & 10
12 in binary: 1100
10 in binary: 1010
             ----
Result:       1000 = 8

console.log(12 & 10); // Output: 8

Use Case: Checking if a number is even: num & 1 === 0

|

Bitwise OR (|)

The OR operator returns 1 if at least one bit is 1.

// Example: 12 | 10
12 in binary: 1100
10 in binary: 1010
             ----
Result:       1110 = 14

console.log(12 | 10); // Output: 14

Use Case: Setting specific bits in flags or permissions.

^

Bitwise XOR (^)

XOR returns 1 when bits are different, 0 when they're the same.

// Example: 12 ^ 10
12 in binary: 1100
10 in binary: 1010
             ----
Result:       0110 = 6

console.log(12 ^ 10); // Output: 6

// XOR Trick: Swapping variables without temp
let a = 5, b = 3;
a = a ^ b; // a = 5 ^ 3 = 6
b = a ^ b; // b = 6 ^ 3 = 5
a = a ^ b; // a = 6 ^ 5 = 3
console.log(a, b); // Output: 3, 5
~

Bitwise NOT (~)

NOT inverts all bits. Due to Two's Complement, ~n equals -(n+1).

// Example: ~5
5 in binary:  00000000000000000000000000000101
~5 in binary: 11111111111111111111111111111010 = -6

console.log(~5);  // Output: -6
console.log(~-1); // Output: 0

// Quick trick: ~n === -(n+1)
console.log(~10 === -11); // true
<<

Left Shift (<<)

Shifts bits to the left, effectively multiplying by 2^n.

// Example: 5 << 2
5 in binary:    101
5 << 2:      10100 = 20

console.log(5 << 2); // Output: 20
console.log(3 << 4); // Output: 48 (3 * 2^4)

// Fast multiplication by powers of 2
console.log(7 << 3); // 7 * 8 = 56
>>

Right Shift (>>)

Shifts bits right while preserving the sign bit.

// Example: 20 >> 2
20 in binary:   10100
20 >> 2:          101 = 5

console.log(20 >> 2); // Output: 5
console.log(-20 >> 2); // Output: -5 (sign preserved)

// Fast division by powers of 2 (floor division)
console.log(15 >> 1); // 15 / 2 = 7 (floor)

Interactive Bitwise Calculator

🧮 Try Bitwise Operations

Result: 5 & 3 = 1

Real-World Applications

🔐 Permission Systems

Many systems use bitwise operations for managing user permissions efficiently.

// Permission flags
const PERMISSIONS = {
  READ: 1,    // 001
  WRITE: 2,   // 010
  EXECUTE: 4  // 100
};

// Grant multiple permissions
let userPerms = PERMISSIONS.READ | PERMISSIONS.WRITE;

// Check if user has specific permission
function hasPermission(userPerms, permission) {
  return (userPerms & permission) === permission;
}

console.log(hasPermission(userPerms, PERMISSIONS.READ)); // true
console.log(hasPermission(userPerms, PERMISSIONS.EXECUTE)); // false

🎨 Color Manipulation

RGB colors are often stored as single integers and manipulated with bitwise operations.

// Extract RGB components from hex color
function extractRGB(color) {
  const r = (color >> 16) & 0xFF;  // Red
  const g = (color >> 8) & 0xFF;   // Green
  const b = color & 0xFF;          // Blue
  return { r, g, b };
}

// Combine RGB into single value
function combineRGB(r, g, b) {
  return (r << 16) | (g << 8) | b;
}

const purple = 0x800080;
console.log(extractRGB(purple)); // {r: 128, g: 0, b: 128}

⚡ Performance Optimizations

Bitwise operations are extremely fast and used in performance-critical code.

// Fast even/odd check
function isEven(n) {
  return (n & 1) === 0;
}

// Fast multiplication/division by powers of 2
function multiplyBy8(n) {
  return n << 3;  // Much faster than n * 8
}

function divideBy4(n) {
  return n >> 2;  // Much faster than Math.floor(n / 4)
}

// Fast absolute value for 32-bit integers
function fastAbs(n) {
  const mask = n >> 31;
  return (n + mask) ^ mask;
}

🎯 Bit Flags in React

React internally uses bitwise operations for managing component update priorities.

// Feature flags system
const FEATURES = {
  DARK_MODE: 1,      // 0001
  NOTIFICATIONS: 2,  // 0010
  ANALYTICS: 4,      // 0100
  BETA_FEATURES: 8   // 1000
};

class FeatureManager {
  constructor() {
    this.flags = 0;
  }
  
  enable(feature) {
    this.flags |= feature;
  }
  
  disable(feature) {
    this.flags &= ~feature;
  }
  
  isEnabled(feature) {
    return (this.flags & feature) !== 0;
  }
}

const features = new FeatureManager();
features.enable(FEATURES.DARK_MODE | FEATURES.NOTIFICATIONS);
console.log(features.isEnabled(FEATURES.DARK_MODE)); // true

🔢 Hash Functions

Bitwise operations are fundamental in creating hash functions for data structures.

// Simple hash function using bitwise operations
function simpleHash(str) {
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    const char = str.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash; // Convert to 32-bit integer
  }
  return hash;
}

// Bloom filter implementation
class BloomFilter {
  constructor(size) {
    this.size = size;
    this.bits = new Array(Math.ceil(size / 32)).fill(0);
  }
  
  add(item) {
    const hash1 = this.hash1(item) % this.size;
    const hash2 = this.hash2(item) % this.size;
    
    this.setBit(hash1);
    this.setBit(hash2);
  }
  
  setBit(index) {
    const arrayIndex = Math.floor(index / 32);
    const bitIndex = index % 32;
    this.bits[arrayIndex] |= (1 << bitIndex);
  }
}

🎮 Game Development

Bitwise operations are crucial in game development for state management and optimizations.

// Game entity state flags
const ENTITY_FLAGS = {
  ALIVE: 1,
  MOVING: 2,
  ATTACKING: 4,
  DEFENDING: 8,
  INVISIBLE: 16
};

class GameEntity {
  constructor() {
    this.flags = ENTITY_FLAGS.ALIVE;
  }
  
  addState(state) {
    this.flags |= state;
  }
  
  removeState(state) {
    this.flags &= ~state;
  }
  
  hasState(state) {
    return (this.flags & state) !== 0;
  }
  
  // Toggle state
  toggleState(state) {
    this.flags ^= state;
  }
}

const player = new GameEntity();
player.addState(ENTITY_FLAGS.MOVING | ENTITY_FLAGS.ATTACKING);
console.log(player.hasState(ENTITY_FLAGS.MOVING)); // true

External Resources & Further Learning

📖

Books & Advanced Reading

  • 📚 "Hacker's Delight" by Henry S. Warren Jr.
  • 📚 "Computer Systems: A Programmer's Perspective" by Bryant & O'Hallaron
  • 📚 "The Art of Computer Programming" by Donald Knuth
  • 📚 "Bitwise: A Life in Code" by David Auerbach

Quick Reference Cheat Sheet

// Common Bitwise Patterns

// Check if number is power of 2
function isPowerOfTwo(n) {
  return n > 0 && (n & (n - 1)) === 0;
}

// Count number of set bits (1s)
function countSetBits(n) {
  let count = 0;
  while (n) {
    count += n & 1;
    n >>= 1;
  }
  return count;
}

// Find the only non-duplicate in array
function findSingle(arr) {
  return arr.reduce((a, b) => a ^ b, 0);
}

// Check if nth bit is set
function isBitSet(num, n) {
  return (num & (1 << n)) !== 0;
}

// Set nth bit
function setBit(num, n) {
  return num | (1 << n);
}

// Clear nth bit
function clearBit(num, n) {
  return num & ~(1 << n);
}

// Toggle nth bit
function toggleBit(num, n) {
  return num ^ (1 << n);
}