16

How would i go about finding the number of 'zero' bits in C++. Suppose I have an integer;

int value = 276; 

For which I have the bits 100010100, but how do I count the zeros?

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 3
    Check here: http://graphics.stanford.edu/~seander/bithacks.html – Chris Lutz Nov 22 '10 at 10:11
  • 2
    Try to google for "bit counting" – Bojan Komazec Nov 22 '10 at 10:13
  • Did you forget about 23 leading zeros? Yeah, yeah, I know it depends on integer representation ;) – mih Nov 22 '10 at 10:22
  • I spent a fair amount of time looking into optimizing `popcount` for Tanimoto calculations recently; here is a good summary of several methods: http://www.dalkescientific.com/writings/diary/archive/2008/07/05/bitslice_and_popcount.html Ended up using a 16-bit LUT, it's simple and negligibly slower than the fastest. That's if you care about speed at all. – Dmitri Nov 23 '10 at 03:44

13 Answers13

27

If you want efficiency then there is a good implementation in the book "Hackers Delight"

22 instructions branch free.

unsigned int count_1bits(unsigned int x)
{
    x = x - ((x >> 1) & 0x55555555);
    x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
    x = x + (x >> 8);
    x = x + (x >> 16);
    return x & 0x0000003F;
}

unsigned int count_0bits(unsigned int x)
{
    return 32 - count_1bits(x);
}

I'll try to explain how it works. It is a divide-and-conquer algorithm.

(x >> 1) & 0x55555555

Shifts all bits 1 step to the right and takes the least significant bit of every bit pair.

0x55555555 -> 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 (16x2 bit pairs)

So basically you will have the following table of all 2 bit permutations.

1. (00 >> 1) & 01 = 00
2. (01 >> 1) & 01 = 00
3. (10 >> 1) & 01 = 01
4. (11 >> 1) & 01 = 01

x - ((x >> 1) & 0x55555555);

Then you subtract these from the non shifted pairs.

1. 00 - 00 = 00 => 0 x 1 bits
2. 01 - 00 = 01 => 1 x 1 bits
3. 10 - 01 = 01 => 1 x 1 bits
4. 11 - 01 = 10 => 2 x 1 bits

x = x - ((x >> 1) & 0x55555555);

So now we have changed every 2 bit pair so that their value is now the number of bits of their corresponding original 2 bit pairs... and then we continue in similar way with 4 bit groups, 8 bit groups, 16 bit groups and final 32 bit.

If you want a better explanation buy the book, there are a lot of good explanation and discussions of alternative algorithms etc...

ronag
  • 49,529
  • 25
  • 126
  • 221
  • Except count_0bits() assumes that an unsigned int is 32 bits on your platform and compiler of choice... – user Nov 22 '10 at 13:13
  • Indeed. One would need to do separate implementation for 16,32 and 64 bits. Could be done with meta-template programming. – ronag Nov 22 '10 at 13:25
  • you miss one line: `x = (x + (x >> 4)) & 0x0f0f0f0f;`. before `x = x + (x >> 8);` – libo Jul 07 '23 at 07:13
18

The easiest most naive way is to just iterate over the bits and count:

size_t num_zeroes = 0;

for(size_t i = 0; i < CHAR_BIT * sizeof value; ++i)
{
  if ((value & (1 << i)) == 0)
    ++num_zeroes;
}

There are all number of better (for different values of "better") ways, but this is quite clear, very terse (code-wise), and doesn't require a bunch of setup.

One micro-optimization that might be considered an improvement is to not compute the mask to test each bit, instead shift the value and always test the rightmost bit:

for(size_t i = 0; i < CHAR_BIT * sizeof value; ++i, value >>= 1)
{
  if ((value & 1) == 0)
    ++num_zeroes;
}
unwind
  • 391,730
  • 64
  • 469
  • 606
  • Another micro-optimization would be to remove the ==0 (and modify the condition a bit), since 0==false and 1==true. – Kricket Nov 22 '10 at 13:38
  • 5
    @Kelsey: but that is just silly, the compiler will do that at very low levels of optimizations (or maybe even at none). Much better to keep it for clarity. – unwind Nov 22 '10 at 15:38
9

You can do 32 minus the number of bits set.

Goz
  • 61,365
  • 24
  • 124
  • 204
  • better to 8*sizeof(int) - (number of set bits), but the suggestion is good – BЈовић Nov 22 '10 at 10:32
  • @VJo: does the C++ standard mandate an 8 bit byte then? Technically, in C you can't assume that sizeof returns the size in 8 bit bytes. – JeremyP Nov 22 '10 at 11:01
  • @JeremyP You are right. c++ standard, 1.7-1 tells "A byte is at least large enough to contain any member of the basic execution character set and is composed of a contiguous sequence of bits, the number of which is implementation-defined." – BЈовић Nov 22 '10 at 11:23
  • 1
    Yup, you'd need `CHAR_BIT * sizeof(int)` and even that only tells you the size in memory, not how many bits are actually needed for the value representation of int. That you get from `std::numeric_limits::digits + std::numeric_limits::is_signed` – MSalters Nov 23 '10 at 09:54
9

If you use GCC, you can try built-in functions:

int __builtin_popcount (unsigned int x) 
int __builtin_ctz (unsigned int x)
int __builtin_clz (unsigned int x)

See GCC Documentation for details.

mih
  • 515
  • 3
  • 13
7

Kernighan way of counting set bits

unsigned int v; // count the number of bits set in v
unsigned int c; // c accumulates the total bits set in v
for (c = 0; v; c++)
{
  v &= v - 1; // clear the least significant bit set
}

Can be easily adapted for the task given. A number of iterations here is equal to a number of bits set.

I also recommend the link above for various other ways of solving this and others types of bit-related tasks. There also is a single line example of obtaining bit count implemented in macros.

Basilevs
  • 22,440
  • 15
  • 57
  • 102
  • This is a very useful addition - many important algorithms yield sparse distributions of *set* bits in very large (multiple word) bit vectors, or matrices. – Brett Hale Apr 14 '22 at 08:55
5

I'm surprised no one has mentioned this one:

int num_zero_bits = __builtin_popcount(~num);

This will give the number of zero bits in num when used with GCC.

17andLearning
  • 477
  • 1
  • 8
  • 19
3

By far the most obvious solution is a lookup table.

/* Assuming CHAR_BITS == 8 */
int bitsPerByte[256] = { 8, 7, 7, 6, /* ... */ };
int bitsInByte(unsigned char c) { return bits[c]; }
MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 3
    I think that "counting the number of zero bits" is by far a more obvious solution to the problem of "How do I count the number of zero bits in an integer?" – R. Martinho Fernandes Nov 22 '10 at 10:20
3

There is a great book for this kind of stuff : Hacker's Delight (yeah, the name sucks : it has nothing to do with security but exclusively bit-twiddling). It provides several algorithms to count '1' bits, the best can also be found here (although the book has explanations that this website doesn't).

Once you know the '1' bits count, just subtract it to the number of bits in your type representation.

icecrime
  • 74,451
  • 13
  • 99
  • 111
  • 2
    the meaning of the word 'Hacking' or 'Hacker' is misunderstood. It is not just about security. In this context, it just means "clever or quick fix" (See Wikipedia). :) – SysAdmin Nov 22 '10 at 10:40
  • 1
    @SysAdmin: unfortunately the damn media twisted the meaning of hack/hacking/hacker into that of crack/cracking/cracker. Some of us still resist, though. – R. Martinho Fernandes Nov 22 '10 at 10:44
  • @SysAdmin: true indeed, but every time I recommend this book I get stupid comments about security :) – icecrime Nov 22 '10 at 10:48
2

With c++20, you can use the standard library function bit_width and popcountto achieve this:

#include <bit>
#include <cstdint>
#include <iostream>
 
int main()
{
    uint32_t i = 276;
    std::cout << std::bit_width(i) - std::popcount(i) << '\n'; // output: 6
}
Chao
  • 121
  • 1
  • 2
1

Do a one's compliment then count the 1s.

count_zero_bits( x ) = count_one_bits( ~x );

Implement the code to count the ones.

template< typename I > 
int count_one_bits( I i )
{
   size_t numbits = 0;
   for( ; i != 0; i >>= 1 )
   {
      numbits += i&1;
   }
}

although there is an issue with my function if i is a negative number because >> will put 1 bits into the right hand side so you will get a never-terminating loop. If there is a templated way to enforce an unsigned type that would be ideal.

Once you have that then:

template< typename I > int count_zero_bits( I i )
{
   return count_one_bits( ~i );
}

will work.

CashCow
  • 30,981
  • 5
  • 61
  • 92
0

According to me , the simplest way to get the zero bit count in a positive integer is the following piece of code.

int get_zero_bit_count(int num)
{
    int cnt = 0;

    while(num > 0)
        {
            int and_num = num & 1;

            if (and_num != num) cnt++;

            num >>= 1; 
        }

        return cnt;
    }

This piece of code is easy to understand and is selp explainatory . This works well for positive integers.

user43609
  • 113
  • 1
  • 2
  • 5
0

Expanding on ronag's answer, which other users have mentioned leads to wrong results (his algorithm works only up to a value of x = 15), here is an updated version of the algorithm:

uint8_t count_1bits(uint32_t x) {
    x = x - ((x >> 1) & 0x55555555);
    x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
    x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
    x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
    x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF);
    return x & 0x3F;
}

uint8_t count_0bits(uint32_t x)    {
    return 32 - count_1bits(x);
}

The explanation of the first line from ronag is correct, however, the remaining lines are using a different approach. In the first line, through the shifting and subtracting, each 2-bit pair will contain the number of bits that were set in that pair in the original number. The rest of the lines recursively fold those numbers together by adding the lsb of each 2n-bit group to the msb of that pair shifted by n, so that the 2n-bit group contains the number of bits that was set in that group in the original number:

01110110: 0111 (7 bits were set in the original number) 0110 (6 bits were set in the original number)
-> 01110110 & 00001111 + (01110110 >> 4) & 00001111
= 0110 + 0111
= 1101

The above algorithm works for 32 bit integers, but can easily be adapted by changing the constants to the correct bit-length so that the pattern stays the same (e.g. 0x5555... = 0101..., 0x0f0f... = 00001111... etc.) and adding/removing the appropriate shifts

milch
  • 986
  • 8
  • 13
0
#include <bits/stdc++.h>
using namespace std;
#define ll long long int


int main() {
    ll a;
    cin>>a;
    ll ones=__builtin_popcountll(~a);
    ll zero=__builtin_clzll(a);
    ll num=abs(ones-zero);
    cout<<num<<"\n";
    return 0;
}

with the help of builtin gcc functions i.e. popcount(counts number of set bit) and clz(count number of leading zero's) we can calculate the number of zero bit in an integer

you can read about them here https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html, https://www.geeksforgeeks.org/builtin-functions-gcc-compiler/

  • See [Why should I not #include ?](https://stackoverflow.com/q/31816095) and [Why using namespace std is bad practice](https://stackoverflow.com/questions/1452721). – prapin Oct 09 '22 at 14:17
  • The site GeeksForGeeks is of very low quality. Do not use it, nor refer to it. The first 3 horrible lines are just an example. – prapin Oct 09 '22 at 14:18