0

How would I scan an integer (in binary) from left to right instead of right to left? I know that I can start from the left and try every bit, and then record the leftmost bit, but is there a faster way? Is there a built-in function that can instantly find the leftmost active bit (that is a 1) in an integer?

I know that for right to left, I can do something like

int myInt = 1234;
for(int i = 0; i < 32; i++) {
  int curr_bit = myInt & (1 << i);
  // do something with curr_bit
}

But, I want to start off at the leftmost available bit, and I want its number "x" so that 1 << x will point to that exact digit (Just as a side note, I am trying to implement repeated squaring, and I need this in my code).

Any help would be greatly appreciated!

phuclv
  • 37,963
  • 15
  • 156
  • 475
NL628
  • 418
  • 6
  • 21
  • 1
    @NickyC That's not my question...I want to be able to get the index of the leftmost bit instantly...sorry if my question is kind of unclear. If I right shift, then if the integer in binary is something like 1010, then I would have to right shift from the leftmost 2^32 bit 28 times before I get the first bit that is a 1 – NL628 Dec 09 '17 at 04:38
  • 1
    OK, now I understand your question. Have you ever heard of logarithm? –  Dec 09 '17 at 04:51
  • 1
    Just try it. `int leftmost_bit_index = log2(myInt);` –  Dec 09 '17 at 04:56
  • 1
    And you have measured and compared it with others? –  Dec 09 '17 at 04:59

5 Answers5

4

If you're interested in the actual fastest answer (at least on a desktop), here it is: use the _bit_scan_reverse intrinsic supported by Intel Compiler and Clang (maybe Visual Studio and GCC as well).

#include "immintrin.h"
int main() { printf("%i", _bit_scan_reverse(9)); }

Result: 3 (because 1<<3 = 8 is the highest bit set in 9).

Documentation

If you're worried about portability (as you should be with all proprietary extensions like this one), just include a fallback function and use the preprocessor to select the implementation you need:

#ifdef __SSE__ // All SSE processors support bsf/bsr
#include "immintrin.h"
static inline int bit_scan_reverse(int n) { return _bit_scan_reverse(n); }
#else
// Fallback implementation here
#endif

Note that the _bit_scan_reverse returns an unspecified value for n=0. If this is a problem you can add a ternary to the code in bit_scan_reverse: return n == 0 ? 0 : _bit_scan_reverse(n);.

4

This is called Find first set and most modern architectures have an instruction to do that quickly. In C++20 it can be done with std::countl_zero in the <bit> header

int left_most_bit_pos = sizeof(myInt)*CHAR_BIT - std::countl_zero(myInt);
int left_most_bit = myInt & (1 << left_most_bit_pos)
phuclv
  • 37,963
  • 15
  • 156
  • 475
0

Java has a method in the Integer class called highestOneBit(int value) which returns an int value with at most a single one-bit, in the position of the most significant (left most) bit that is set in the specified int value. It is implemented like this:

int highestOneBit(int value)
{
    value |= (value >>  1);
    value |= (value >>  2);
    value |= (value >>  4);
    value |= (value >>  8);
    value |= (value >> 16);
    return value - (value >> 1);
}
Justin Randall
  • 2,243
  • 2
  • 16
  • 23
-1

Use this:

int left_most_bit = myInt & (1 << (sizeof myInt * CHAR_BIT - 1));

How does it work?

  • sizeof myInt returns the size of the variable myInt in bytes
  • CHAR_BIT is a (possibly) platform-dependent macro that tells you how many bits are there in a byte, which is typically 8
  • Shift 1 left by that gets the leftmost bit.

Works great in O(1) time because both sizeof myInt and CHAR_BIT are compile-time constants, so the whole expression (1 << (sizeof myInt * CHAR_BIT - 1)) is a compile-time constant, too. The compiler can then apply maximum optimization to it.

iBug
  • 35,554
  • 7
  • 89
  • 134
  • this helps, thank you so much. could you guys please explain the downvote to this answer? I think it's perfectly fine... – NL628 Dec 09 '17 at 04:41
  • There was a small mistake. I missed the `-1` at the end of the size calculation. – iBug Dec 09 '17 at 04:43
  • @NL628 What about voting a helpful answer up and accepting it? – iBug Dec 09 '17 at 04:47
  • 7
    This answer gives the current value of the most significant bit in the word, but I think the questioner wants the index of the first bit that is set -- which is a different thing. – Jeremy Friesner Dec 09 '17 at 04:50
  • `sizeof` gives you the size in `char`s. That may or may not be what someone thinks "byte" means. As the name suggests, `CHAR_BIT` tells you how many bits there are in a `char`. – Pete Becker Dec 09 '17 at 13:30
  • 4
    This doesn't answer the question. It gives the value of the leftmost bit; the question is how to find the leftmost bit whose value is 1. – Pete Becker Dec 09 '17 at 13:35
-1

iBug's answer is very interesting, and I had never thought of doing it this way. If you're doing huge calculations where you want to find the leftmost digit many many times, I would recomment __builtin_clz in c++11. If you perform the snippet

for(int i = 31 - __builtin_clz; i >= 0; i--) {
    int left_most_bit = myInt & (1 << i);
}

This will start from the left_most_bit and work it's way to the right. Hope this helps! Implementation of __builtin_clz

NL628
  • 418
  • 6
  • 21
  • It's a fine answer but there is just no way that `sizeof` has more overhead than a for loop. – Justin Randall Dec 09 '17 at 04:51
  • 1
    @JustinRandall Oh, sorry my answer just loops through ever digit. One repetition of this loop will get the first digit, and this will loop through the rest. the OP said in his problem statement that she was learning repeated squaring, so I just posted the code I normally use for this algorithm –  Dec 09 '17 at 04:53
  • 1
    Oh this helps soo much! Yes, I was trying to implement repeated squaring, and this fits my code exactly thank you so much! I wish I could upvote more than once :O – NL628 Dec 09 '17 at 05:00
  • 2
    I think `__builtin_clz` is a GCC extension, not a C++11 feature (not that that's bad, as I suggested an extension as well; just thought it's important to know). – David Zhao Akeley Dec 09 '17 at 05:05
  • 1
    @bobjoe628 You know you're allowed to just use singular `they` instead of changing OP's gender halfway through the sentence, right? – David Zhao Akeley Dec 09 '17 at 05:16
  • C++11 (and any other version of the C++ standard) does not provide `__builtin_clz`. That `__` at the beginning is a hint: it means that the name is reserved for use by the implementation. – Pete Becker Dec 09 '17 at 13:28