2012-01-04 247 views
1

我有一个int参数,其中可能的值为1,2,4,8,16,32,64。在C++中获取位偏移量

我需要知道当前值的位偏移量,即分别对于每个值返回1,2,3,4,5或6。

实现该目标的最简单方法是什么?

+2

你的意思是两个幂(6是不是一个)?在这种情况下,“位偏移”将是对数基2? – 2012-01-04 15:13:12

+0

是的,请澄清。最好的问候, – 2012-01-04 15:16:31

+1

幼稚的方法是循环和测试,但可能有一个本地CPU指令可以在一条指令中完成。 (“获得最少(或最多)显着位”) – 2012-01-04 15:17:50

回答

4

你这里有多个答案:http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious 最简单的幸福,假设你有一个unsigned int v您输入值:

unsigned int r = 0; // r will be lg(v) 

while (v >>= 1) // unroll for more speed... 
{ 
    r++; 
} 

但它会在这个过程中改变诉

编辑:你的情况,如果你是100%肯定你的输入和int和2的幂,查找表可能是最简单和最快的

+1

Endianess与它有什么关系? – Skizz 2012-01-04 15:23:11

+3

我相当肯定你的代码是正确的,没有考虑到它所运行的硬件系统的字节顺序。 – dasblinkenlight 2012-01-04 15:23:57

+0

这是正确的。 – Jonathan 2012-01-04 15:24:52

1

这里有一个版本,只做五次迭代最多为32位值,与lezebulon的答案不同,后者的最坏情况是32次迭代。适应64位值将此版本的迭代次数增加到6次,其他次数增加到64次。

int get_pos (unsigned v) 
{ 
    int s=16,p=0,m=0xffff; 

    while (s) 
    { 
    if (v>>s) p += s; 
    v = (v | (v >> s)) & m; 
    s >>= 1; 
    m >>= s; 
    } 

    return p; 
} 
0

所有你需要做的就是循环和每次移动一点。但使用开关盒的方法更快。列出两个为你。

//more code but awesomely fast 
int getBitOffset1(int d) { 
    switch(d) { 
    case 1: return 1; 
    case 2: return 2; 
    case 4: return 3; 
    case 8: return 4; 
    case 16: return 5; 
    case 32: return 6; 
    /* keep adding case upto sizeof int*8 */ 
    } 
} 

//less code, the loop goes 64 times max 
int getBitOffset2(int d) { 
    int seed=0x01; 
    int retval=0; 
    do{ 
    if(seed<<retval == d) { 
     break; 
    } 
    retval++; 
    }while(retval<=sizeof(int)*8); 
    return retval+1; 
} 

int main() { 
    printf("%d\n", getBitOffset2(32)); 
    printf("%d\n", getBitOffset2(1)); 
    return 0; 
}