web-dev-qa-db-ja.com

C ++で数値が2のべき乗かどうかをテストする最も簡単な方法は何ですか?

次のような関数が必要です。

// return true iff 'n' is a power of 2, e.g.
// is_power_of_2(16) => true  is_power_of_2(3) => false
bool is_power_of_2(int n);

誰も私がこれを書く方法を提案できますか?この種のアルゴリズムが見つかる優れたWebサイトを教えてください。

82
Ant

(n & (n - 1)) == 0 最高です。ただし、n = 0の場合は誤ってtrueを返すため、可能であれば、明示的に確認する必要があります。

http://www.graphics.stanford.edu/~seander/bithacks.html には、これを含む巧妙なビット調整アルゴリズムの大規模なコレクションがあります。

167
Anonymous

2の累乗では、1ビットのみが設定されます(符号なしの数値の場合)。何かのようなもの

bool powerOfTwo = !(x == 0) && !(x & (x - 1));

正常に動作します。 2のべき乗より1つ小さいビットはすべて1であるため、ビット単位でANDする必要があります。

符号なしの数値を想定していたので、== 0テスト(元々忘れてしまった、すみません)で十分です。符号付き整数を使用している場合は、0以上のテストが必要になる場合があります。

78
Adam Wright

バイナリの2のべき乗は次のようになります。

1: 0001
2: 0010
4: 0100
8: 1000

常に正確に1ビットが設定されていることに注意してください。唯一の例外は符号付き整数です。例えば値が-128の8ビット符号付き整数は次のようになります。

10000000

したがって、数値がゼロより大きいことを確認した後、巧妙な小さなハックを使用して、1つだけのビットが設定されていることをテストできます。

bool is_power_of_2(int x) {
    return x > 0 && !(x & (x−1));
}

少し調整するために here を参照してください。

46
Matt Howells

アプローチ#1:

数値を2で除算して確認します。

時間の複雑さ:O(log2n)。

アプローチ#2:

ビット単位AND直前の数値と数値はゼロに等しくなければなりません。

例:数値= 8 8のバイナリ:1 0 0 0 7のバイナリ:0 1 1 1および両方の数値のビット単位ANDは0 0 0 0 = 0。

時間の複雑さ:O(1)。

アプローチ#3:

ビット単位のXORは、直前の数値と両方の数値の合計である必要があります。

例:数値= 8 8のバイナリ:1 0 0 0 7のバイナリ:0 1 1 1およびビット単位のXOR両方の数値は1 1 1 1 = 15です。

時間の複雑さ:O(1)。

http://javaexplorer03.blogspot.in/2016/01/how-to-check-number-is-power-of-two.html

13
Raj Dixit
bool is_power_of_2(int i) {
    if ( i <= 0 ) {
        return 0;
    }
    return ! (i & (i-1));
}
7
Rob Wells

2の累乗については、次も当てはまります。

n&(-n)== n

注:条件はn = 0に対して真ですが、2のべき乗ではありません。
これが機能する理由は次のとおりです。
-nは、nの2の補数です。 -nは、nと比較して、nの右端の設定ビットの左側のすべてのビットを反転させます。 2の累乗の場合、設定ビットは1つだけです。

6
FReeze FRancis
return n > 0 && 0 == (1 << 30) % n;
3
Yuxiang Zhang

C++で数値が2のべき乗かどうかをテストする最も簡単な方法は何ですか?

Bit Manipulation Instructions を備えた最新のIntelプロセッサを使用している場合は、次を実行できます。他の人がすでにそれに答えているため、ストレートC/C++コードは省略しますが、BMIが利用できないか有効になっていない場合は必要です。

bool IsPowerOf2_32(uint32_t x)
{
#if __BMI__ || ((_MSC_VER >= 1900) && defined(__AVX2__))
    return !!((x > 0) && _blsr_u32(x));
#endif
    // Fallback to C/C++ code
}

bool IsPowerOf2_64(uint64_t x)
{
#if __BMI__ || ((_MSC_VER >= 1900) && defined(__AVX2__))
    return !!((x > 0) && _blsr_u64(x));
#endif
    // Fallback to C/C++ code
}

GCC、ICC、およびClangは、__BMI__でBMIサポートを通知します。 AVX2が利用可能で有効になっている の場合、Visual Studio 2015以降のMicrosoftコンパイラーで利用可能です。必要なヘッダーについては、 SIMD組み込み関数のヘッダーファイル を参照してください。

私は通常、i686でコンパイルする場合に_blsr_u64_LP64_でガードします。 Clangは少し異なる組み込みシンボルnamを使用するため、少しの回避策が必要です。

#if defined(__GNUC__) && defined(__BMI__)
# if defined(__clang__)
#  ifndef _tzcnt_u32
#   define _tzcnt_u32(x) __tzcnt_u32(x)
#  endif
#  ifndef _blsr_u32
#    define  _blsr_u32(x)  __blsr_u32(x)
#  endif
#  ifdef __x86_64__
#   ifndef _tzcnt_u64
#    define _tzcnt_u64(x) __tzcnt_u64(x)
#   endif
#   ifndef _blsr_u64
#     define  _blsr_u64(x)  __blsr_u64(x)
#   endif
#  endif  // x86_64
# endif  // Clang
#endif  // GNUC and BMI

この種のアルゴリズムが見つかる優れたWebサイトを教えてください。

このウェブサイトはよく引用されます: Bit Twiddling Hacks

2
jww

ブール型の短絡と比較が遅いという事実により、フォローアップはほとんどの投票された回答よりも速くなります。

int isPowerOfTwo(unsigned int x)
{
  return x && !(x & (x – 1));
}

Xを0にできないことがわかっている場合

int isPowerOfTwo(unsigned int x)
{
  return !(x & (x – 1));
}
2
Margus

C++ 20には std::ispow2 自分で実装する必要がない場合、まさにこの目的に使用できます。

#include <bit>
static_assert(std::ispow2(16));
static_assert(!std::ispow2(15));
2
Rakete1111

これは最速または最短の方法ではありませんが、非常に読みやすいと思います。だから私はこのようなことをします:

bool is_power_of_2(int n)
  int bitCounter=0;
  while(n) {
    if ((n & 1) == 1) {
      ++bitCounter;
    }
    n >>= 1;
  }
  return (bitCounter == 1);
}

バイナリは2の累乗に基づいているため、これは機能します。 1ビットのみが設定された数値は、2の累乗でなければなりません。

1
Jere.Jones

これは最速です:

if(1==__builtin_popcount(n))
1
F10PPY

別の方法を次に示します。この場合、|の代わりに&を使用します。

bool is_power_of_2(int x) {
    return x > 0 && (x<<1 == (x|(x-1)) +1));
}
0
Chethan

C++で可能です

int IsPowOf2(int z) {
double x=log2(z);
int y=x;
if (x==(double)y)
return 1;
else
return 0;
}
0
Jay Ponkia