unsigned int count(unsigned int x) {
int pop = 0;
while(x) {
pop = pop + (x & 1);
x = x >> 1;
}
return pop;
}
計測結果
./a.out 2.69s user 0.00s system 99% cpu 2.700 total
3.ビットが立っている数だけループする
x & (x-1)が、xの最下位の1ビットを0にした数になることを利用します。
unsigned int count(unsigned int x) {
int pop = 0;
while(x) {
pop = pop + 1;
x = x & (x - 1);
}
return pop;
}
計測結果
./a.out 1.73s user 0.01s system 99% cpu 1.740 total
4.分割統治法を使う
シンプルに2ビットずつ16の部分に分割して並列処理的にカウントする。
unsigned int count(unsigned int x) {
x = x - ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x + (x >> 4)) & 0x0f0f0f0f;
x = x + (x >> 8);
x = x + (x >> 16);
return x & 0x0000003F;
}
計測結果
./a.out 0.48s user 0.00s system 100% cpu 0.480 total
unsigned int count(unsigned int x) {
unsigned int n;
n = (x >> 1) & 033333333333;
x = x - n;
n = (n >> 1) & 033333333333;
x = x - n;
x = (x + (x >> 3)) & 030707070707;
return x % 63;
}
計測結果
./a.out 0.49s user 0.01s system 99% cpu 0.500 total