2012-01-04 1 views
1

intパラメータに1,2,4,8,16,32,64の可能な値があります。C++でビットオフセットを取得

現在の値のビットオフセットを知る必要があります。つまり、それぞれの値がそれぞれ1,2,3,4,5または6を返します。

これを達成する最も簡単な方法は何ですか?

+2

2の累乗(6は1ではない)を意味しましたか?この場合、「ビットオフセット」は対数の底2ですか? –

+0

はい、明確にしてください。よろしくお願いします。 –

+1

単純なアプローチはループとテストですが、単一の命令でこれを行うネイティブCPU命令がある可能性があります。 (少なくとも(またはほとんどの重要なビットを得る) –

答えて

4

あなたはここに複数の回答があります。

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

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

が、それはプロセスでVを変更します:あなたはunsigned int型Vにご入力値を持っていると仮定すると、http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious 最も簡単なビーイングを。

編集:あなたは、あなたの入力であり、int型と2のパワーを100%確信している場合は、あなたの場合には、ルックアップテーブルは、最も簡単かつ最速の

+1

エンディアンは何と関係していますか? – Skizz

+3

私は、実行中のハードウェアシステムのエンディアンに関係なく、コードが正しいことをかなり確信しています。 – dasblinkenlight

+0

それは正しいです。 – Jonathan

1

かもしれここだけ5回の反復を行い、バージョンですlezebulonの答えは32回の反復の最悪の場合とは異なり、せいぜい32ビットの値である。 64ビット値に適合させると、このバージョンの反復回数は6に増加し、もう1つは最悪で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; 
} 
関連する問題