int a = 12;
たとえば、12のバイナリは1100なので、右から3番目のビットが設定されているため、答えは3になります。
a
の最後に設定されたビットの位置が欲しい。誰にどうすればいいのか教えてもらえますか?.
[〜#〜] note [〜#〜]:位置のみが必要ですが、ここではビットを設定またはリセットしたくありません。したがって、stackoverflowに関する質問の重複ではありません。
この回答 右端のセットビットの設定解除 は、符号なし整数または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
最下位セットビットの(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
があり、代わりにlong
とlong long
を使用している場合に使用する必要があります/ int
。
ここで2s-complementのプロパティを使用できます。
数値の2の補数を見つける最も速い方法は、右端のセットビットを取得し、すべてをその左にフリップすることです。
例:4ビットシステムを検討してください
4 = 0100
4の2の補数= 1100、つまり-4のみ
4&(-4)= 0100。
設定ビットは1つしかなく、右端の設定ビットは4であることに注意してください
同様に、これをnに対して一般化できます。
n&(-n)には、実際にはnの右端のセットビット位置にある1つのセットビットのみが含まれます。
n&(-n)にはセットビットが1つしかないため、2の累乗です。
最後に、次のようにしてビット位置を取得できます。
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/ これを理解するのに役立ちました。
nおよび(n&(n-1))のビットごとのxorを実行することにより、右端のセットビットの位置を見つけることができます。
int pos = n ^ (n&(n-1));
私はこれを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);
}
a & 1
は0です。そうである場合は、0になるまで1つ右にシフトします。シフトする回数は、設定されている右端のビットが右から何ビットかということです。
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;
}
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(回答)。
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
x&〜(x-1)は、1である最下位ビットを分離します。
インデックス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
の適切なビット数を取得します。