この提案 (およびここに示されている他の提案) を現在のコードと照らし合わせて確認する必要があります。ビットシフトが最も効率的な方法であるか、読みやすさを最適化する必要がある場合は違いがごくわずかであることがわかる場合があります。
いずれにせよ、これは高速であることが保証されているものではなく、試してベンチマークするものと考えてください。
可能な値は 64 個しかないため、次のようなものを使用できます。
int getSetBit (unsigned long x) {
if (x == 0x8000000000000000UL) return 63;
if (x == 0x4000000000000000UL) return 62;
if (x == 0x2000000000000000UL) return 61;
if (x == 0x1000000000000000UL) return 60;
if (x == 0x0800000000000000UL) return 59;
if (x == 0x0400000000000000UL) return 58;
:
if (x == 0x0000000000000002UL) return 1;
return 0;
}
その方が高速であることに気付くかもしれませんが、ソリューションは通常、標準の範囲外の多くのもの (最適化戦略、データ キャッシング、パイプラインなど) の影響を受けます。
標準 C から離れることを厭わない場合、多くの環境には、次のような使用できる最適化されたものがありますgcc
。
int __builtin_ffs (unsigned int x)
// Returns one plus the index of the least significant
// 1-bit of x, or if x is zero, returns zero.
もちろん、その場合、long
を 2 つのint
タイプに分割し、それぞれを個別に確認する必要がある場合があります (テストされていませんが、一般的なアイデアを得る必要があります)。
if (x < 0x80000000UL) return __builtin_ffs((unsigned int)x) - 1;
return __builtin_ffs((unsigned int)(x>>32)) -1 + 32;
または、からの出力を__builtin_clzl()
操作してビット位置を取得することもできます (先頭のゼロ カウントが得られます) unsigned long
。ここでgcc
ビルトインを見ることができます。