我有int
参数,可能的值为1,2,4,8,16,32,64。
我需要知道当前值的位偏移,即每个值分别返回1,2,3,4,5或6。
实现这一目标的最简单方法是什么?
答案 0 :(得分: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++;
}
但它会在此过程中改变v。
编辑:在你的情况下,如果你100%确定你的输入是和int和2的幂,查找表可能是最简单和最快的
答案 1 :(得分:1)
这是一个版本,对于32位值最多只能进行5次迭代,这与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;
}
答案 2 :(得分:0)
您需要做的就是每次循环和移位。但是使用switch case有一种更快的方法。列出这两个。
//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;
}