How To Find The Leading Number Of Zero's In a Number using C

后端 未结 6 2111
星月不相逢
星月不相逢 2021-02-04 21:07

for example,if i have number 64,then its binary representation would be 0000 0000 0000 0000 0000 0000 0100 0000 so leading number of zero\'s is 25. remember i have to calculate

相关标签:
6条回答
  • 2021-02-04 21:16

    I would go with:

    unsigned long clz(unsigned long n) {
        unsigned long result = 0;
        unsigned long mask = 0;
        mask = ~mask;
        auto size = sizeof(n) * 8;
        auto shift = size / 2;
        mask >>= shift;
        while (shift >= 1) {
            if (n <= mask) {
                result += shift;
                n <<= shift;
            }
            shift /= 2;
            mask <<= shift;
        }
        return result;
    }
    
    0 讨论(0)
  • 2021-02-04 21:22

    Right shift is your friend.

        int input = 64;
        int sample = ( input < 0 ) ? 0 : input;
        int leadingZeros = ( input < 0 ) ? 0 : 32;
    
        while(sample) {
            sample >>= 1;
            --leadingZeros;
        }
        printf("Input = %d, leading zeroes = %d\n",input, leadingZeros);
    
    0 讨论(0)
  • 2021-02-04 21:23

    I just found this problem at the top of the search results and this code:

    int pop(unsigned x) {
        unsigned n;
        n = (x >> 1) & 033333333333;
        x = x - n;
        n = (n >> 1) & 033333333333;
        x = x - n;
        x = (x + (x >> 3)) & 030707070707;
        return x % 63;
    }
    
    int nlz(unsigned x) {
        x = x | (x >> 1);
        x = x | (x >> 2);
        x = x | (x >> 4);
        x = x | (x >> 8);
        x = x | (x >>16);
        return pop(~x);
    }
    

    where pop counts 1 bits, is several times faster than the first (upvoted) answer.

    I didn't notice, question was about 64 bits numbers, so here:

    int nlz(unsigned long x) {
        unsigned long y;
        long n, c;
        n = 64;
        c = 32;
        do {
            y = x >> c;
            if (y != 0) {
                n = n - c;
                x = y;
            }
            c = c >> 1;
        } while (c != 0);
        return n - x;
    }
    

    is a 64 bits algorithm, again several times faster than the mentioned above.

    0 讨论(0)
  • 2021-02-04 21:28

    See here for the 32-bit version and other great bit-twiddling hacks.

    // this is like doing a sign-extension
    // if original value was   0x00.01yyy..y
    // then afterwards will be 0x00.01111111
    x |= (x >> 1);
    x |= (x >> 2);
    x |= (x >> 4);
    x |= (x >> 8);
    x |= (x >> 16);
    x |= (x >> 32);
    

    and after that you just need to return 64 - numOnes(x). A simple way to do that is numOnes32(x) + numOnes32(x >> 32) where numOnes32 is defined as:

    int numOnes32(unsigned int x) {
        x -= ((x >> 1) & 0x55555555);
        x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
        x = (((x >> 4) + x) & 0x0f0f0f0f);
        x += (x >> 8);
        x += (x >> 16);
        return(x & 0x0000003f);
    }
    

    I haven't tried out this code, but this should do numOnes64 directly (in less time):

    int numOnes64(unsigned long int x) {
         x = ((x >> 1) & 0x5555555555555555L) + (x & 0x5555555555555555L);
         x = ((x >> 2) & 0x3333333333333333L) + (x & 0x3333333333333333L);
         // collapse:
         unsigned int v = (unsigned int) ((x >>> 32) + x);
         v = ((v >> 4) + v) & 0x0f0f0f0f) + (v & 0x0f0f0f0f);
         v = ((v >> 8) & 0x00ff00ff) + (v & 0x00ff00ff);
         return ((v >> 16) & 0x0000ffff) + (v & 0x0000ffff);
    }
    
    0 讨论(0)
  • 2021-02-04 21:29

    Because the logarithm base 2 roughly represents the number of bits required to represent a number, it might be useful in the answer:

    irb(main):012:0> 31 - (Math::log(64) / Math::log(2)).floor()
    => 25
    irb(main):013:0> 31 - (Math::log(65) / Math::log(2)).floor()
    => 25
    irb(main):014:0> 31 - (Math::log(127) / Math::log(2)).floor()
    => 25
    irb(main):015:0> 31 - (Math::log(128) / Math::log(2)).floor()
    => 24
    

    Of course, one downside to using log(3) is that it is a floating-point routine; there are probably some supremely clever bit-tricks to find the number of leading zero bits in integers, but I can't think of one off the top of my head...

    0 讨论(0)
  • 2021-02-04 21:34

    Using floating points is not the right answer....

    Here is an algo that I use to count the TRAILING 0... change it for Leading... This algo is in O(1) (will always execute in ~ the same time, or even the same time on some CPU).

    int clz(unsigned int i)
    {
      int zeros;
      if ((i&0xffff)==0) zeros= 16, i>>= 16; else zeroes= 0;
      if ((i&0xff)==0) zeros+= 8, i>>= 8;
      if ((i&0xf)==0) zeros+= 4, i>>= 4;
      if ((i&0x3)==0) zeros+= 2, i>>= 2;
      if ((i&0x1)==0) zeros+= 1, i>>= 1;
      return zeroes+i;
    }
    
    0 讨论(0)
提交回复
热议问题