Tristan Sweeney

← Back to blog

Counting Ones

Published on 2017-12-4 by Tristan Sweeney

Foo
So, say you have a bitstring, `11010110`, and you want to count how many ones are in it.

Counting Ones

Okay, this one is a short one. Really, it’s mostly on here solely so that I can find it later, and because I can’t a concise explanation on the web anywhere.

So, say you have a bitstring, 11010110, and you want to count how many ones are in it. Trivially, you can perform the below logic to count it, running in O(n_bits) time.

int n = 0b11010110; // Yes, C++ 14 introduced binary literals! Yippie!
int count = 0;
while(n > 0)
{
if (n & 1)
count ++;
n >>= 1;
}

O(64) isn’t too bad, but it feels like there’s got to be a better solution (and of course, it’s one of those ones that leaves you marveling at how simple it is).

Prismoskills (apparently a skills/interview prep site) highlights that the below logic will operate in O(n_ones) time. It operates with a bit of bitwise logic that’s tricky to understand at first but actually quite intuitive.

int n = 0b11010110; // Yes, C++ 14 introduced binary literals! Yippie!
int count=0;
while (n!=0)
{
n = n & (n-1);
count++;
}

Let us look at the values in n, n-1, and n & (n-1) for each iteration, to get a sense for this magic.

nn-1n&(n-1)count++

1101 0111

1101 0110

1101 01101

1101 0110

1101 0101

1101 01002

1101 0100

1101 0011

1101 00003

1101 0000

1100 1111

1100 00004

1100 0000

1011 1111

1000 00005

1000 0000

0111 1111

0000 00006

So, what looked like a strange abuse of bitwise operations is actually quite elegant. The algorithm generates a bitmask by performing n-1 that masks out the lowest one in n at that iteration. This operation knocks a one off of n on each iteration, therefore running in O(n_bits) time.

Counting Zeros

Suppose you wanted to instead count how many zeros are in a bitstring. Either inverting the bits with ~ (a bitwise not) and putting the result through the one-counting algorithm or subtracting the number of ones from sizeof(type) (C/C++) will give you the number of zeros.

Both approaches should run in near-identical runtime, with the invert-and-count-ones approach being marginally faster due to not having to load the literal sizeof(int) into a register from constant memory.

Hamming Distance

For the curious, this came from a coding challenge on leetcode to calculate the “Hamming Distance” between two numbers, the count of locations in them where their bits differ.

The hamming distance between 0001 and 0100 would be 2, since two locations differ. Performing an XOR on the two numbers then counting the ones gives the hamming distance between two values.

Written by Tristan Sweeney

← Back to blog
  • Favicon Fun

    9/17/2024
    Favicon Fun
    photo by Astro

    I love the Astro homepage favicon effect, and replicated it on my site.

  • Ransom Note

    5/3/2020
    Ransom Note
    photo by Jamie Eckle

    Given the text for a ransom note, determine if enough letters exist in a magazine to create it.

  • Breaking down Subsum Equals K

    4/29/2020
    Breaking down Subsum Equals K
    photo by Meghan Vestal

    given an array of integers, find the number of continuous subarrays equal to `k`.

  • Revivifying the Blog

    4/11/2020
    Revivifying the Blog

    I recently had a friend come across my blog, and was promptly shamed for having a certificate more out of date than the VCR. Such an embarrassment couldn't rest, and so I cleaned up my act a bit.

  • Apt install on a Disconnected Wireless System

    6/8/2018
    Apt install on a Disconnected Wireless System
    photo by Google

    I just was installing ubuntu on a platform that only has wireless capabilities, and decided to install the server edition to minimize overhead / avoid having an X server + desktop environment to disable. Woe, the server edition of Ubuntu ships with no wireless utilities, because nobody in their right mind would run a wireless server.

  • Let's Encrypt HTTPS on DD-WRT

    6/5/2018
    Let's Encrypt HTTPS on DD-WRT
    photo by DD-WRT

    I run a DD-WRT router on a Netgear WNDR4500 router. It's been in my life since I can remember, and came along with me to college. A while back I loaded the DD-WRT firmware onto it, and it's been serving like a champ ever since.