8

I have an std::uint32_t and want to check if exactly one bit is set. How can I do this without iterating over all bits like this? In other words, can the following function be simplified?

static inline bool isExactlyOneBitSet(std::uint32_t bits)
{
    return ((bits & 1) == bits
        || (bits & 1 << 1) == bits
        || (bits & 1 << 2) == bits
        // ...
        || (bits & 1 << 31) == bits
        );
}

Bonus: It would be nice if the return value was the one found bit or else 0.

static inline bool isExactlyOneBitSet(std::uint32_t bits)
{
if (bits & 1) {return 1;}
else if  (bits & 1 << 1) {return 1 << 1;};
//...
else if  (bits & 1 << 31) {return 1 << 31;};

return 0;
}
Fabian
  • 4,001
  • 4
  • 28
  • 59

4 Answers4

28

So you want to know if a number is power of 2 or not? Well there is a famous algorithm for that, you can simply do,

check_bit(std::uint32_t bits)
{
    return bits && !(bits & (bits-1));
}

Any power of 2 when subtracted by 1 is all 1s. e.g,

4 - 1 = 3 (011)
8 - 1 = 7 (0111)

The bitwise and of any power of 2 and any number 1 less than it will give 0. So we can verify if a number is power of 2 or not by using the expression, n&(n-1).

It will fail when n=0, so we have to add an extra and condition.

For finding the position of bit, you can do:

int findSetBit(std::uint32_t bits)
{
    if (!(bits && !(bits & (bits-1))))
        return 0;
    return log2(bits) + 1;
}

Extra Stuffs

In gcc, you can use __builtin_popcount(), to find the count of set bits in any number.

#include <iostream>

int main()
{
   std::cout << __builtin_popcount (4) << "\n";
   std::cout << __builtin_popcount (3) << "\n";

   return 0;
}

Then check if count is equal to 1 or not.

Regarding count, there is another famous algorithm, Brian Kernighan’s Algorithm. Google it up, it finds count in log(n) time.

Abhishek Keshri
  • 3,074
  • 14
  • 31
5

Here's a solution for your bonus question (and of course, it is a solution for your original question as well):

std::uint32_t exactlyOneBitSet(std::uint32_t bits) {
    return bits&(((bool)(bits&(bits-1)))-1);
}

This compiles down to only 4 instructions on x86_64 with clang:

0000000000000000 <exactlyOneBitSet(unsigned int)>:
   0:   8d 4f ff                lea    -0x1(%rdi),%ecx
   3:   31 c0                   xor    %eax,%eax
   5:   85 f9                   test   %edi,%ecx
   7:   0f 44 c7                cmove  %edi,%eax
   a:   c3                      retq   
geza
  • 28,403
  • 6
  • 61
  • 135
1

C++20 has a function that does exactly that: std::has_single_bit(value). It's in the header <bit>.

jlh
  • 4,349
  • 40
  • 45
0

Given a number n, the following expression will determine if exactly one bit is set (in any language): (n & (n - 1)) == 0.

To check if a number is exact power of 2, You can also use the expression (n & (-n)) == n.

In JavaScript, however, these expression fail at -2^31.

Note the bitwise AND (&) operator here.

PKV
  • 424
  • 4
  • 6