在C ++中testing一个数是否是2的幂的最简单的方法是什么?
我需要这样的function:
// return true iff 'n' is a power of 2, eg // is_power_of_2(16) => true is_power_of_2(3) => false bool is_power_of_2(int n);
任何人都可以build议我怎么写这个? 你能告诉我一个很好的网站,这种algorithm可以find?
(n & (n - 1)) == 0
是最好的。 但是,请注意,如果n = 0,它将错误地返回true,所以如果可能的话,您将需要明确检查它。
http://www.graphics.stanford.edu/~seander/bithacks.html有大量的聪明的位扭曲algorithm,包括这一个。;
二的幂将只有一个位集(无符号数)。 就像是
bool powerOfTwo = !(x == 0) && !(x & (x - 1));
将工作正常; 一个小于2的幂在较低有效位中全部为1,所以必须按位与0进行比较。
正如我假设无符号数字,== 0testing(我原来忘记,对不起)是足够的。 如果您使用带符号整数,您可能需要> 0testing。
二进制的权力是这样的:
1: 0001 2: 0010 4: 0100 8: 1000
请注意,总是有一个比特集。 唯一的例外是有符号整数。 例如一个值为-128的8位有符号整数看起来像:
10000000
因此,在检查数字大于零之后,我们可以使用一点巧妙的方法来testing是否只设置了一个位。
bool is_power_of_2(int x) { return x > 0 && !(x & (x−1)); }
为更多位twiddling看见这里 。
方法1:
将数字除以2以检查它。
时间复杂度: O(log2n)。
方法2:
按位与前一个数字的数字应该等于零。
例如:数字= 8二进制8:1 0 0 0二进制7:0 1 1 1,两个数字的按位与是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
bool is_power_of_2(int i) { if ( i <= 0 ) { return 0; } return ! (i & (i-1)); }
对于任何2的幂,下面也成立。
N'( – N)==Ñ
注意:对于n = 0,条件是成立的,尽pipe它不是2的幂。
这个工程的原因是:
-n是n的二进制补码。 -n将比n翻转n的最右边的位的左边。 对于2的幂,只有一个设定位。
在C ++中testing一个数是否是2的幂的最简单的方法是什么?
如果您的现代英特尔处理器具有位操作说明 ,则可以执行以下操作。 它省略了直接的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内在函数的标题文件 。
我通常用_blsr_u64
来防止_LP64_
在i686上编译。 铿锵需要一个小的解决方法,因为它使用了一个稍微不同的内在符号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
你能告诉我一个很好的网站,这种algorithm可以find?
这个网站经常被引用: Bit Twiddling Hacks 。
return n > 0 && 0 == (1 << 30) % n;
由于布尔短路以及比较速度慢的原因,以下方式会更快,因此最多的答案是答案。
int isPowerOfTwo(unsigned int x) { return x && !(x & (x – 1)); }
如果你知道x不能是0那么
int isPowerOfTwo(unsigned int x) { return !(x & (x – 1)); }
这不是最快或最短的方式,但我认为它是非常可读的。 所以我会做这样的事情:
bool is_power_of_2(int n) int bitCounter=0; while(n) { if ((n & 1) == 1) { ++bitCounter; } n >>= 1; } return (bitCounter == 1); }
这是可行的,因为二进制是基于两个幂。 任何只有一个位的数字必须是2的幂。
这里是另一种方法,在这种情况下使用|
而不是&
:
bool is_power_of_2(int x) { return x > 0 && (x<<1 == (x|(x-1)) +1)); }
有可能通过c ++
int IsPowOf2(int z) { double x=log2(z); int y=x; if (x==(double)y) return 1; else return 0; }
另一种方法(可能不是最快的)是确定ln(x)/ ln(2)是否是一个整数。
这是T-SQL(SQL Server)中的移位方法:
SELECT CASE WHEN @X>0 AND (@X) & (@X-1)=0 THEN 1 ELSE 0 END AS IsPowerOfTwo
它比做对数快四倍(首先获得小数结果,第二组获得整数集并比较)