Quantcast
Channel: What is the fastest/most efficient way to find the highest set bit (msb) in an integer in C? - Stack Overflow
Viewing all articles
Browse latest Browse all 36

Answer by ChuckCottrill for What is the fastest/most efficient way to find the highest set bit (msb) in an integer in C?

$
0
0

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

#include <stdio.h>#include <stdlib.h>unsigned intLog2(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 intLog2_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 intLog2_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 intLog2_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);}

Viewing all articles
Browse latest Browse all 36

Trending Articles