我需要这样的功能:
// 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);
有谁能建议我怎么写这个?你能告诉我一个可以找到这种算法的好网站吗?
答案 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 = 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
比对数四次快得多(第一次设置得到十进制结果,第二次得到整数设置和比较)