2012-01-04 137 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; 
}