web-dev-qa-db-ja.com

Cで最も右に設定されたビットの位置を取得する方法

int a = 12;

たとえば、12のバイナリは1100なので、右から3番目のビットが設定されているため、答えは3になります。

aの最後に設定されたビットの位置が欲しい。誰にどうすればいいのか教えてもらえますか?.

[〜#〜] note [〜#〜]:位置のみが必要ですが、ここではビットを設定またはリセットしたくありません。したがって、stackoverflowに関する質問の重複ではありません。

12
ram singh

この回答 右端のセットビットの設定解除 は、符号なし整数または2の補数として表される符号付き整数の右端のセットビットの取得方法と設定解除方法の両方を示します

右端のセットビットを取得

x & -x
// or
x & (~x + 1)

unset rightmost set bit

x &= x - 1
// or
x -= x & -x  // rhs is rightmost set bit

なぜ機能するのか

x:                     leading bits  1  all 0
~x:           reversed leading bits  0  all 1
~x + 1 or -x: reversed leading bits  1  all 0
x & -x:                       all 0  1  all 0

たとえば、x = 112、そして単純にするために8ビットを選択しますが、すべてのサイズの整数で考え方は同じです。

// example for get rightmost set bit
x:             01110000
~x:            10001111
-x or ~x + 1:  10010000
x & -x:        00010000

// example for unset rightmost set bit
x:             01110000
x-1:           01101111
x & (x-1):     01100000
15
qeatzy

最下位セットビットの(0ベースの)インデックスを見つけることは、特定の整数の末尾のゼロの数を数えることと同じです。コンパイラによっては、このための組み込み関数があります。たとえば、gccとclangのサポート __builtin_ctz です。 MSVCの場合、独自のバージョンを実装する必要があります。別の質問の この答え は、MSVC組み込み関数を使用するソリューションを示しています。

1から始まるインデックスを探しているとすると、目的の結果を得るには、ctzの結果に1を追加するだけです。

int a = 12;
int least_bit = __builtin_ctz(a) + 1; // least_bit = 3

a == 0の場合、この操作は未定義であることに注意してください。さらに __builtin_ctzl__builtin_ctzll があり、代わりにlonglong longを使用している場合に使用する必要があります/ int

7
jdoerrie

ここで2s-complementのプロパティを使用できます。
数値の2の補数を見つける最も速い方法は、右端のセットビットを取得し、すべてをその左にフリップすることです。
例:4ビットシステムを検討してください
4 = 0100
4の2の補数= 1100、つまり-4のみ
4&(-4)= 0100。
設定ビットは1つしかなく、右端の設定ビットは4であることに注意してください
同様に、これをnに対して一般化できます。
n&(-n)には、実際にはnの右端のセットビット位置にある1つのセットビットのみが含まれます。
n&(-n)にはセットビットが1つしかないため、2の累乗です。
最後に、次のようにしてビット位置を取得できます。

log2(n&(-n))+ 1

6
FReeze FRancis

Nの左端のビットは、次の式を使用して取得できます:n&〜(n-1)

これが機能するのは、(n-1)を計算すると、実際には、右端のビットまですべてのゼロが1になり、右端のビットが0になるからです。次に、NOTをとると、次のようになります。 x =〜(元の数からのビット)+(右端の1ビット)+後続ゼロ

ここで(n&x)を実行すると、nとxの両方で1である唯一のビットが右端のビットであるため、必要なものが得られます。

ふwwwwwww ..:sweat_smile:

http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/ これを理解するのに役立ちました。

4
user3503070

nおよび(n&(n-1))のビットごとのxorを実行することにより、右端のセットビットの位置を見つけることができます。

int pos = n ^ (n&(n-1));
3
Ravi Shankar

私はこれをHAKMEMから来たことをメモして継承しました(試してみてください here )。符号付き整数と符号なし整数の両方、論理または算術右シフトで機能します。また、かなり効率的です。

#include <stdio.h>

int rightmost1(int n) {
    int pos, temp;
    for (pos = 0, temp = ~n & (n - 1); temp > 0; temp >>= 1, ++pos);
    return pos;
}

int main()
{
    int pos = rightmost1(16);
    printf("%d", pos);
}
1
Nate Glenn

a & 1は0です。そうである場合は、0になるまで1つ右にシフトします。シフトする回数は、設定されている右端のビットが右から何ビットかということです。

1
dbush

bush 'aソリューションによると、これを試してください:

int rightMostSet(int a){
      if (!a) return -1;  //means there isn't any 1-bit
      int i=0;
      while(a&1==0){ 
        i++; 
        a>>1;
      }
      return i;
    }
0
Fartab

log2(((num-1)^ num)+1);を返す;

例による説明:12-1100

num-1 = 11 = 1011

num ^(num-1)= 12 ^ 11 = 7(111)

num ^(num-1))+ 1 = 8(1000)

log2(1000)= 3(回答)。

0
instance
int main(int argc, char **argv)
{
    int setbit;
    unsigned long d;
    unsigned long n1;
    unsigned long n = 0xFFF7;
    double nlog2 = log(2);

    while(n)
    {
        n1 = (unsigned long)n & (unsigned long)(n -1);
        d = n - n1;
        n = n1;

        setbit = log(d) / nlog2;
        printf("Set bit: %d\n", setbit);
    }

    return 0;
}

そして結果は以下の通りです。

Set bit: 0
Set bit: 1
Set bit: 2
Set bit: 4
Set bit: 5
Set bit: 6
Set bit: 7
Set bit: 8
Set bit: 9
Set bit: 10
Set bit: 11
Set bit: 12
Set bit: 13
Set bit: 14
Set bit: 15
0
Austin

x&〜(x-1)は、1である最下位ビットを分離します。

0
lava

インデックス0から32ビットすべてをチェックし、左側に向かって作業する必要があります。ビット単位で、その位置に1ビットのaがあり、ゼロ以外の値が返される場合、そのビットが設定されていることを意味します。

#include <limits.h>

int last_set_pos(int a) {
  for (int i = 0; i < sizeof a * CHAR_BIT; ++i) {
    if (a & (0x1 << i)) return i;
  }
  return -1; // a == 0
}

一般的なシステムでは、intは32ビットですが、sizeof a * CHAR_BITは、サイズが異なっていても、aの適切なビット数を取得します。

0
Ryan Haining