find the index of the highest bit set of a 32-bit number without loops obviously

前端 未结 11 1302
梦毁少年i
梦毁少年i 2021-01-07 01:56

Here\'s a tough one(atleast i had a hard time :P):

find the index of the highest bit set of a 32-bit number without using any loops.

相关标签:
11条回答
  • 2021-01-07 02:29

    With recursion:

    int firstset(int bits) {        
         return (bits & 0x80000000) ? 31 : firstset((bits << 1) | 1) - 1;
    }
    
    • Assumes [31,..,0] indexing
    • Returns -1 if no bits set
    • | 1 prevents stack overflow by capping the number of shifts until a 1 is reached (32)
    • Not tail recursive :)
    0 讨论(0)
  • 2021-01-07 02:30

    Let n - Decimal number for which bit location to be identified start - Indicates decimal value of ( 1 << 32 ) - 2147483648 bitLocation - Indicates bit location which is set to 1

    public int highestBitSet(int n, long start, int bitLocation)
    {
        if (start == 0)
        {
            return 0;
        }
        if ((start & n) > 0)
        {
            return bitLocation;
        }
        else
        {
            return highestBitSet(n, (start >> 1), --bitLocation);
        }
    }
    
        long i = 1;
        long startIndex = (i << 31);
        int bitLocation = 32;
        int value = highestBitSet(64, startIndex, bitLocation);
        System.out.println(value);
    
    0 讨论(0)
  • 2021-01-07 02:31

    Paislee's solution is actually pretty easy to make tail-recursive, though, it's a much slower solution than the suggested floor(log2(n));

    int firstset_tr(int bits, int final_dec) {
    
         // pass in 0 for final_dec on first call, or use a helper function
    
         if (bits & 0x80000000) {
          return 31-final_dec;
         } else {
          return firstset_tr( ((bits << 1) | 1), final_dec+1 );
         }
    }
    

    This function also works for other bit sizes, just change the check, e.g.

    if (bits & 0x80) {   // for 8-bit
      return 7-final_dec;
    }
    
    0 讨论(0)
  • 2021-01-07 02:33

    Note that what you are trying to do is calculate the integer log2 of an integer,

    #include <stdio.h>
    #include <stdlib.h>
    
    unsigned int
    Log2(unsigned long x)
    {
        unsigned long n = x;
        int bits = sizeof(x)*8;
        int step = 1; int k=0;
        for( step = 1; step < bits; ) {
            n |= (n >> step);
            step *= 2; ++k;
        }
        //printf("%ld %ld\n",x, (x - (n >> 1)) );
        return(x - (n >> 1));
    }
    

    Observe that you can attempt to search more than 1 bit at a time.

    unsigned int
    Log2_a(unsigned long x)
    {
        unsigned long n = x;
        int bits = sizeof(x)*8;
        int step = 1;
        int step2 = 0;
        //observe that you can move 8 bits at a time, and there is a pattern...
        //if( x>1<<step2+8 ) { step2+=8;
            //if( x>1<<step2+8 ) { step2+=8;
                //if( x>1<<step2+8 ) { step2+=8;
                //}
            //}
        //}
        for( step2=0; x>1L<<step2+8; ) {
            step2+=8;
        }
        //printf("step2 %d\n",step2);
        for( step = 0; x>1L<<(step+step2); ) {
            step+=1;
            //printf("step %d\n",step+step2);
        }
        printf("log2(%ld) %d\n",x,step+step2);
        return(step+step2);
    }
    

    This approach uses a binary search

    unsigned int
    Log2_b(unsigned long x)
    {
        unsigned long n = x;
        unsigned int bits = sizeof(x)*8;
        unsigned int hbit = bits-1;
        unsigned int lbit = 0;
        unsigned long guess = bits/2;
        int found = 0;
    
        while ( hbit-lbit>1 ) {
            //printf("log2(%ld) %d<%d<%d\n",x,lbit,guess,hbit);
            //when value between guess..lbit
            if( (x<=(1L<<guess)) ) {
               //printf("%ld < 1<<%d %ld\n",x,guess,1L<<guess);
                hbit=guess;
                guess=(hbit+lbit)/2;
                //printf("log2(%ld) %d<%d<%d\n",x,lbit,guess,hbit);
            }
            //when value between hbit..guess
            //else
            if( (x>(1L<<guess)) ) {
                //printf("%ld > 1<<%d %ld\n",x,guess,1L<<guess);
                lbit=guess;
                guess=(hbit+lbit)/2;
                //printf("log2(%ld) %d<%d<%d\n",x,lbit,guess,hbit);
            }
        }
        if( (x>(1L<<guess)) ) ++guess;
        printf("log2(x%ld)=r%d\n",x,guess);
        return(guess);
    }
    

    Another binary search method, perhaps more readable,

    unsigned int
    Log2_c(unsigned long x)
    {
        unsigned long v = x;
        unsigned int bits = sizeof(x)*8;
        unsigned int step = bits;
        unsigned int res = 0;
        for( step = bits/2; step>0; )
        {
            //printf("log2(%ld) v %d >> step %d = %ld\n",x,v,step,v>>step);
            while ( v>>step ) {
                v>>=step;
                res+=step;
                //printf("log2(%ld) step %d res %d v>>step %ld\n",x,step,res,v);
            }
            step /= 2;
        }
        if( (x>(1L<<res)) ) ++res;
        printf("log2(x%ld)=r%ld\n",x,res);
        return(res);
    }
    

    And because you will want to test these,

    int main()
    {
        unsigned long int x = 3;
        for( x=2; x<1000000000; x*=2 ) {
            //printf("x %ld, x+1 %ld, log2(x+1) %d\n",x,x+1,Log2(x+1));
            printf("x %ld, x+1 %ld, log2_a(x+1) %d\n",x,x+1,Log2_a(x+1));
            printf("x %ld, x+1 %ld, log2_b(x+1) %d\n",x,x+1,Log2_b(x+1));
            printf("x %ld, x+1 %ld, log2_c(x+1) %d\n",x,x+1,Log2_c(x+1));
        }
        return(0);
    }
    
    0 讨论(0)
  • 2021-01-07 02:36

    well from what I know the function Log is Implemented very efficiently in most programming languages, and even if it does contain loops , it is probably very few of them , internally So I would say that in most cases using the log would be faster , and more direct. you do have to check for 0 though and avoid taking the log of 0, as that would cause the program to crash.

    0 讨论(0)
提交回复
热议问题