How to Implement Bitwise Operations for Math Algorithms in JavaScript

The trekhleb/javascript-algorithms repository implements bitwise operations for math algorithms through pure functions in src/algorithms/math/bits, using core operators like &, ^, and >>> to manipulate 32-bit integer representations.

Bitwise algorithms provide efficient, low-level solutions for mathematical problems by operating directly on binary representations. The trekhleb/javascript-algorithms repository demonstrates this approach through a dedicated collection of utilities that handle everything from counting set bits to converting IEEE-754 binary arrays into floating-point numbers.

Core Bitwise Utilities in the Repository

The repository organizes its bitwise math algorithms under src/algorithms/math/bits/. Each module exports a single, focused utility function that operates on JavaScript numbers using bitwise operators.

Counting Set Bits with countSetBits

The countSetBits function determines how many 1s appear in the binary representation of an integer. Located in src/algorithms/math/bits/countSetBits.js, this implementation uses an unsigned right shift to avoid sign extension issues with negative numbers.

The algorithm repeatedly extracts the least significant bit using number & 1, increments a counter if the result is 1, then shifts the number right using >>>. This continues until the number becomes 0.

import countSetBits from './src/algorithms/math/bits/countSetBits';

// 13 in binary is 1101, which has three set bits
console.log(countSetBits(13)); // → 3

Calculating Bit Length

The bitLength function, found in src/algorithms/math/bits/bitLength.js, returns the number of bits required to represent a positive integer in binary. This is useful for determining the "size" of a number in terms of binary storage.

The implementation right-shifts the input number until it becomes 0, incrementing a counter on each iteration. The final counter value represents the bit length.

import bitLength from './src/algorithms/math/bits/bitLength';

// 19 in binary is 10011, which requires 5 bits
console.log(bitLength(19)); // → 5

Finding Differing Bits Between Integers

The bitsDiff function in src/algorithms/math/bits/bitsDiff.js calculates the Hamming distance between two integers—the number of bit positions where the two numbers differ.

This utility leverages the XOR (^) operator, which produces a 1 in each bit position where the corresponding bits of the two operands differ. The function then counts the set bits in this XOR result using the countSetBits utility, demonstrating the repository's pattern of modular composition.

import bitsDiff from './src/algorithms/math/bits/bitsDiff';

// 29 is 11101, 15 is 01111
// They differ at positions 4 and 2 (0-indexed from right)
console.log(bitsDiff(29, 15)); // → 2

Advanced Implementation: IEEE-754 Floating Point Conversion

Beyond integer manipulation, the repository includes bitsToFloat in src/algorithms/math/binary-floating-point/bitsToFloat.js, which converts a 32-bit IEEE-754 binary array into a JavaScript floating-point number.

This implementation demonstrates sophisticated bitwise decomposition:

  1. Sign extraction: The first bit determines the sign (0 for positive, 1 for negative)
  2. Exponent extraction: The next 8 bits form the exponent, stored with a bias of 127
  3. Mantissa reconstruction: The remaining 23 bits represent the fractional part, which is combined with an implicit leading 1 (for normalized numbers)
import bitsToFloat from './src/algorithms/math/binary-floating-point/bitsToFloat';

// IEEE-754 representation of 9.5
// Sign: 0, Exponent: 10000010 (130), Mantissa: 001100...
const bits = [
  0, // sign bit
  1,0,0,0,0,0,1,0, // exponent (130 - 127 = 3)
  0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // mantissa
];

console.log(bitsToFloat(bits)); // → 9.5

Common Patterns in Bitwise Algorithm Design

The repository's bitwise utilities follow consistent architectural patterns that ensure clarity and reusability:

Pure Functions: All utilities are side-effect free. Input numbers remain immutable, and outputs depend solely on inputs, facilitating predictable testing and debugging.

Direct Bitwise Operators: The code leverages JavaScript's bitwise operators (&, |, ^, <<, >>>) directly. These operators treat numbers as 32-bit signed integers, making them ideal for low-level bit manipulation despite JavaScript's default 64-bit floating-point number system.

Loop-Based Iteration: Rather than converting numbers to binary strings via toString(2), the algorithms use while loops with bit shifts. This approach is computationally efficient and avoids string allocation overhead.

Modular Composition: Complex operations build upon simpler ones. For example, bitsDiff delegates to countSetBits after performing an XOR, demonstrating how the repository structures code for maximum reuse.

Summary

  • The trekhleb/javascript-algorithms repository implements bitwise operations for math algorithms in src/algorithms/math/bits/ using pure, side-effect-free functions.
  • Core utilities include countSetBits for population count, bitLength for binary magnitude, and bitsDiff for Hamming distance calculations.
  • Advanced implementations like bitsToFloat handle IEEE-754 floating-point conversion through systematic bit extraction of sign, exponent, and mantissa components.
  • Design patterns emphasize direct bitwise operators (&, ^, >>>), loop-based iteration over string conversion, and modular composition where complex algorithms reuse simpler bit utilities.

Frequently Asked Questions

How does JavaScript handle bitwise operations on numbers?

JavaScript stores all numbers as 64-bit IEEE-754 floating-point values, but when you apply bitwise operators (&, |, ^, ~, <<, >>, >>>), the engine converts the operands to 32-bit signed integers, performs the operation, and converts back to 64-bit floating-point. This means bitwise algorithms in JavaScript effectively work with 32-bit integer representations, which the trekhleb/javascript-algorithms repository leverages for consistent bit manipulation.

What is the difference between >> and >>> in the repository's code?

The repository uses the unsigned right shift (>>>) in utilities like countSetBits to ensure that high-order bits are filled with zeros rather than the sign bit. The signed right shift (>>) preserves the sign bit (propagating 1s for negative numbers), which can cause infinite loops when counting bits in negative numbers. The unsigned shift treats the number as a 32-bit unsigned integer, allowing the algorithm to process all bits correctly until the value becomes zero.

Why does the bitsDiff function use XOR instead of comparing bits individually?

The bitsDiff function calculates the Hamming distance between two integers by first applying the XOR (^) operator, which produces a result where each bit is set to 1 only if the corresponding bits of the two inputs differ. This single operation transforms the problem from "compare each bit pair" to "count set bits in one number," which the function then solves by delegating to countSetBits. This approach is computationally efficient (O(1) for the XOR on 32-bit integers) and demonstrates the repository's pattern of composing simple bitwise primitives into higher-level algorithms.

Can these bitwise utilities handle very large integers or BigInt values?

The current implementations in src/algorithms/math/bits/ are designed for standard JavaScript numbers (32-bit integer space) and do not explicitly support BigInt. Since JavaScript bitwise operators convert operands to 32-bit signed integers, values outside the range of -(2^31) to 2^31-1 may lose precision or produce unexpected results. For BigInt support, the algorithms would need to be refactored to use BigInt-specific methods (like toString(2) for conversion and manual bit manipulation) rather than native bitwise operators.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →