在C ++中测试一个数字是2的幂是最简单的方法是什么?

时间:2008-09-20 14:34:00

标签: c++ algorithm bit-manipulation

我需要这样的功能:

// 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);

有谁能建议我怎么写这个?你能告诉我一个可以找到这种算法的好网站吗?

17 个答案:

答案 0 :(得分:163)

(n & (n - 1)) == 0是最好的。但请注意,对于n = 0,它将错误地返回true,因此如果可能,您将需要明确检查它。

http://www.graphics.stanford.edu/~seander/bithacks.html有很多聪明的比特算法,包括这个算法。

答案 1 :(得分:75)

2的幂将只设置一位(对于无符号数)。像

这样的东西
bool powerOfTwo = !(x == 0) && !(x & (x - 1));

工作正常;一个小于2的幂是一个在较低有效位中的1,所以必须和0按位。

当我假设无符号数字时,== 0测试(我原先忘了,对不起)就足够了。你可能想要一个>如果你使用有符号整数,则进行0测试。

答案 2 :(得分:45)

二进制二的权力看起来像这样:

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

请注意,总是设置1位。唯一的例外是带符号整数。例如值为-128的8位有符号整数如下所示:

10000000

因此,在检查数字大于零之后,我们可以使用一个聪明的小工具来测试一个并且只设置一个位。

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

有关更多信息,请参阅here

答案 3 :(得分:12)

方法#1:

将数字除以2以进行检查。

时间复杂度: O(log2n)。

方法#2:

按位和前一个数字的数字应该等于ZERO。

示例:数字= 8 二进制8:1 0 0 0 二进制7:0 1 1 1和两个数字的按位AND为0 0 0 0 = 0。

时间复杂度: O(1)。

方法#3:

按位异或,其前一个数字的数字应该是两个数字的总和。

示例:数字= 8 二进制8:1 0 0 0 二进制7:0 1 1 1和两个数字的按位异或是1 1 1 1 = 15.

时间复杂度: O(1)。

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

答案 4 :(得分:7)

bool is_power_of_2(int i) {
    if ( i <= 0 ) {
        return 0;
    }
    return ! (i & (i-1));
}

答案 5 :(得分:5)

对于任何2的幂,以下也适用。

N'安培;( - N)==Ñ

注意:对于n = 0,条件为真,但它不是2的幂。
这有效的原因是:
-n是n的2s补码。与n相比,-n将n翻转的最右设置位左侧的每一位都设置为n。对于2的幂,只有一个设置位。

答案 6 :(得分:3)

    def main():
        scores = getNumbers()
        print("The average with the lowest score dropped is: ",float(sum(scores))/len(scores))

    def getNumbers():
        scores=[]
        for testNum in range(4):
           print('Enter the score for test number',int(testNum+1),end='')
           scores.append(int(input(': ')))
        scores=[score for score in scores if min(scores)!=score]
        return scores

    main()

答案 7 :(得分:2)

由于布尔短路以及比较缓慢的事实,以下会比最多投票的答案更快。

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

如果你知道x不能为0那么

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

答案 8 :(得分:2)

  

在C ++中测试一个数字是2的幂的最简单方法是什么?

如果您的现代英特尔处理器具有Bit Manipulation Instructions,则可以执行以下操作。它省略了直接的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 is available and enabled时,它可以在Visual Studio 2015及更高版本的Microsoft编译器中使用。有关您需要的标头,请参阅Header files for SIMD intrinsics

我通常使用_blsr_u64保护_LP64_,以防i686进行编译。 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
  

你能告诉我一个可以找到这种算法的好网站吗?

本网站经常被引用:Bit Twiddling Hacks

答案 9 :(得分:1)

这不是最快或最短的方式,但我认为它非常易读。所以我会做这样的事情:

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

这是有效的,因为二进制是基于2的幂。任何只设置一位的数字必须是2的幂。

答案 10 :(得分:1)

这是最快的:

if(1==__builtin_popcount(n))

答案 11 :(得分:0)

我知道这是非常的旧帖子,但是我认为在此处发布此帖子可能会很有趣。


来自 Code-Golf SE (因此,所有功劳归功于撰写此内容的人):Showcase of Languages

(关于 C 的段落,长度36的摘录段

bool isPow2(const unsigned int num){return!!num&!(num&(num-1));}

答案 12 :(得分:0)

在C ++ 20中,有std::ispow2可以用于此目的,如果您不需要自己实现它的话:

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

答案 13 :(得分:0)

可以通过c ++

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

答案 14 :(得分:0)

以下是另一种方法,在这种情况下使用|代替&

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

答案 15 :(得分:-1)

另一种方法(可能不是最快)是确定ln(x)/ ln(2)是否是整数。

答案 16 :(得分:-3)

这是T-SQL(SQL Server)中的位移方法:

SELECT CASE WHEN @X>0 AND (@X) & (@X-1)=0 THEN 1 ELSE 0 END AS IsPowerOfTwo

比对数四次快得多(第一次设置得到十进制结果,第二次得到整数设置和比较)