あなたの機能が正しくありません:それはまだ0
のための無限ループを持っています。テストは次のようになります。あなたはこのアプローチに負の数を扱うことができません
while (n > 0 && !(n & 1))
注意、したがって、あなたの関数は、おそらくunsigned
数の引数を取る必要があり、またはあなたがunsigned
に引数を変換することができます。
unsigned trailing_zeroes(int n) {
unsigned bits = 0, x = n;
if (x) {
while ((x & 1) == 0) {
++bits;
x >>= 1;
}
}
return bits;
}
上記の機能は非常にシンプルで理解しやすいです:
あなたの関数は特殊なケース0
とは、単純なループを使用する必要があります。結果が小さい場合は非常に高速です。 0
に返される値は、0
は実際にはunsigned
タイプの値のビットと同じくらい多くの末尾のゼロがあるため、疑問のある関数のように0
です。
一定のステップ数で、より効率的なアプローチがあります:私たちはいくつかのコンパイラが持つ
while (!(x & 0x0000FFFF)) { bits += 16; x >>= 16; }
への第一歩を変更することにより、任意の大きなint
サイズを扱うことができる
unsigned trailing_zeroes(int n) {
unsigned bits = 0, x = n;
if (x) {
/* assuming `x` has 32 bits: lets count the low order 0 bits in batches */
/* mask the 16 low order bits, add 16 and shift them out if they are all 0 */
if (!(x & 0x0000FFFF)) { bits += 16; x >>= 16; }
/* mask the 8 low order bits, add 8 and shift them out if they are all 0 */
if (!(x & 0x000000FF)) { bits += 8; x >>= 8; }
/* mask the 4 low order bits, add 4 and shift them out if they are all 0 */
if (!(x & 0x0000000F)) { bits += 4; x >>= 4; }
/* mask the 2 low order bits, add 2 and shift them out if they are all 0 */
if (!(x & 0x00000003)) { bits += 2; x >>= 2; }
/* mask the low order bit and add 1 if it is 0 */
bits += (x & 1)^1;
}
return bits;
}
注組み込み関数__builtin_ctz()
を使用して、非常に効率的なアセンブリコードを使用して末尾のゼロ数を数えます。これはC標準関数ではありませんが、移植性の低下を犠牲にして、利用可能であれば使用することをお勧めします。コンパイラのドキュメントを確認してください。ここ
GCC docuemntationから抽象的である:
組み込み関数
:int __builtin_ctz (unsigned int x)
最下位ビット位置から、x
に0ビットの末尾の番号を返します。 x
が0
の場合、結果は不定です。
「__builtin_ctz」を試してください。 –
最も簡単な方法は、 'std :: string'に変換して、それを調べることです。 – user0042
**あなたの**具体的な**質問は何ですか?私たちはコードレビューサービスではありません(サイドローとして、コードは 'n 'の特定の値に対する実装定義の振る舞いを持っています)。 – Olaf