How to find hamming weight in java

The Hamming weight of a number is the count of bits set to 1 in its binary representation. It's also called the popcount (population count) or bit count. This concept comes up in coding interviews, error detection algorithms, and low-level programming.

  • 5 in binary is 101 → Hamming weight = 2
  • 8 in binary is 1000 → Hamming weight = 1
  • 255 in binary is 11111111 → Hamming weight = 8

Real-World Uses

  • Error detection/correction: Hamming codes use bit counts to detect and correct transmission errors
  • Cryptography: Many algorithms work with bit patterns and their weights
  • Feature similarity: Hamming distance measures similarity between binary feature vectors in ML
  • Chess engines: Bitboards represent piece positions; popcount tells you how many pieces are on the board

Three Approaches in Java

Method 1: Division and Remainder


 public static int hammingWeightDivision(int n) {
    int count = 0;
    while (n > 0) {
        if (n % 2 == 1) {
            count++;
        }
        n = n / 2;
    }
    return count;
}

How it works: Each division by 2 right-shifts the number by one bit. The remainder (n % 2) is 1 if the least significant bit was set. The loop ends when all bits are consumed (n reaches 0).

Limitation: Doesn't handle negative integers correctly — the loop exits at 0, missing the sign bit.


Method 2: Bit Masking


public static int hammingWeightBitMask(int n) {
    int count = 0;
    int mask = 1;
    for (int i = 0; i < 32; i++) {
        if ((n & mask) != 0) {
            count++;
        }
        mask <<= 1; // shift mask left by one position
    }
    return count;
}

How it works: The mask starts at 00000000...00000001 and shifts left by one bit each iteration, visiting all 32 positions. (n & mask) != 0 tells us whether that specific bit is set.

Advantage: Works correctly for all 32 bits including the sign bit — handles negative integers.


Method 3: Brian Kernighan's Algorithm (Most Elegant)

This technique exploits the fact that n & (n-1) always clears the lowest set bit of n:

public static int hammingWeightKernighan(int n) {
    int count = 0;
    while (n != 0) {
        n = n & (n - 1); // clears the lowest set bit
        count++;
    }
    return count;
}

Walkthrough for n = 12 (binary 1100):

n = 1100  →  n-1 = 1011  →  n & (n-1) = 1000  (count=1)
n = 1000  →  n-1 = 0111  →  n & (n-1) = 0000  (count=2)
n = 0  → loop exits

Why it's elegant: It only iterates as many times as there are set bits. If only 2 bits are set in a 64-bit number, it runs 2 iterations — not 64.


Complete Example

public class HammingWeight {

    public static int byDivision(int n) {
        int count = 0;
        while (n > 0) {
            if (n % 2 == 1) count++;
            n = n / 2;
        }
        return count;
    }

    public static int byBitMask(int n) {
        int count = 0;
        int mask = 1;
        for (int i = 0; i < 32; i++) {
            if ((n & mask) != 0) count++;
            mask <<= 1;
        }
        return count;
    }

    public static int byKernighan(int n) {
        int count = 0;
        while (n != 0) {
            n = n & (n - 1);
            count++;
        }
        return count;
    }

    public static void main(String[] args) {
        int[] tests = {0, 1, 5, 8, 15, 255};
        for (int val : tests) {
            System.out.printf("%-6d → bitMask=%-3d kernighan=%-3d builtin=%d%n",
                val, byBitMask(val), byKernighan(val), Integer.bitCount(val));
        }
    }
}

Output:

0      → bitMask=0   kernighan=0   builtin=0
1      → bitMask=1   kernighan=1   builtin=1
5      → bitMask=2   kernighan=2   builtin=2
8      → bitMask=1   kernighan=1   builtin=1
15     → bitMask=4   kernighan=4   builtin=4
255    → bitMask=8   kernighan=8   builtin=8

Built-in Java Method

Java provides Integer.bitCount() in java.lang — no import needed. It uses a hardware-level POPCNT instruction on modern CPUs and is significantly faster than any manual implementation:

System.out.println(Integer.bitCount(5));            // 2
System.out.println(Integer.bitCount(255));           // 8
System.out.println(Integer.bitCount(Integer.MAX_VALUE)); // 31
System.out.println(Long.bitCount(Long.MAX_VALUE));   // 63

For production code, always use Integer.bitCount(). The manual implementations are valuable for learning and interview contexts.


Comparing All Approaches

MethodTime ComplexityHandles NegativesNotes
Division & RemainderO(log n)NoMost readable; fails on negative ints
Bit MaskingO(32) = O(1)YesAlways 32 iterations
Brian KernighanO(popcount)PartialFastest when few bits set
Integer.bitCount()O(1)YesUses hardware instruction; use in production

Bonus: Hamming Distance

The Hamming distance between two integers is the number of bit positions where they differ. It's computed with XOR (which marks differing bits) followed by a popcount:

int hammingDistance(int x, int y) {
    return Integer.bitCount(x ^ y);
}

System.out.println(hammingDistance(1, 4));  // 0001 ^ 0100 = 0101 → 2
System.out.println(hammingDistance(3, 5));  // 011 ^ 101 = 110 → 2

No comments :

Post a Comment

Please leave your message queries or suggetions.

Note: Only a member of this blog may post a comment.