简体   繁体   English

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

[英]What's the simplest way to test whether a number is a power of 2 in C++?

I need a function like this:我需要这样的功能:

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

Can anyone suggest how I could write this?谁能建议我怎么写这个? Can you tell me a good web site where this sort of algorithm can be found?你能告诉我一个可以找到这种算法的好网站吗?

(n & (n - 1)) == 0 is best. (n & (n - 1)) == 0是最好的。 However, note that it will incorrectly return true for n=0, so if that is possible, you will want to check for it explicitly.但是,请注意,当 n=0 时它会错误地返回 true,因此如果可能,您需要明确检查它。

http://www.graphics.stanford.edu/~seander/bithacks.html has a large collection of clever bit-twiddling algorithms, including this one. http://www.graphics.stanford.edu/~seander/bithacks.html有大量巧妙的位旋转算法,包括这个。

A power of two will have just one bit set (for unsigned numbers). 2 的幂将只设置一位(对于无符号数)。 Something like就像是

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

Will work fine;会正常工作; one less than a power of two is all 1s in the less significant bits, so must AND to 0 bitwise.一个小于 2 的幂在较低有效位中全为 1,因此必须 AND 到 0 按位。

As I was assuming unsigned numbers, the == 0 test (that I originally forgot, sorry) is adequate.当我假设无符号数字时, == 0 测试(我最初忘记了,抱歉)就足够了。 You may want a > 0 test if you're using signed integers.如果您使用有符号整数,您可能需要 > 0 测试。

Powers of two in binary look like this:二进制中的 2 次幂如下所示:

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

Note that there is always exactly 1 bit set.请注意,始终只设置 1 位。 The only exception is with a signed integer.唯一的例外是带符号整数。 eg An 8-bit signed integer with a value of -128 looks like:例如,值为 -128 的 8 位有符号整数如下所示:

10000000

So after checking that the number is greater than zero, we can use a clever little bit hack to test that one and only one bit is set.因此,在检查该数字大于零之后,我们可以使用巧妙的一点点技巧来测试是否设置了一位且仅设置了一位。

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

For more bit twiddling see here .欲了解更多信息,请参见此处

Approach #1:方法#1:

Divide number by 2 reclusively to check it.将数字除以 2 以进行检查。

Time complexity : O(log2n).时间复杂度: O(log2n)。

Approach #2:方法#2:

Bitwise AND the number with its just previous number should be equal to ZERO.按位 AND 与前一个数字的数字应该等于零。

Example: Number = 8 Binary of 8: 1 0 0 0 Binary of 7: 0 1 1 1 and the bitwise AND of both the numbers is 0 0 0 0 = 0.示例: Number = 8 8 的二进制:1 0 0 0 7 的二进制:0 1 1 1 并且两个数字的按位与是 0 0 0 0 = 0。

Time complexity : O(1).时间复杂度: O(1)。

Approach #3:方法#3:

Bitwise XOR the number with its just previous number should be sum of both numbers.按位异或数字与其前一个数字应该是两个数字的总和。

Example: Number = 8 Binary of 8: 1 0 0 0 Binary of 7: 0 1 1 1 and the bitwise XOR of both the numbers is 1 1 1 1 = 15.示例: Number = 8 Binary of 8: 1 0 0 0 Binary of 7: 0 1 1 1 两个数字的按位异或为 1 1 1 1 = 15。

Time complexity : O(1).时间复杂度: O(1)。

http://javaexplorer03.blogspot.in/2016/01/how-to-check-number-is-power-of-two.html 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));
}

In C++20 there is std::ispow2 which you can use for exactly this purpose if you don't need to implement it yourself:在 C++20 中有std::ispow2 ,如果您不需要自己实现它,您可以将其用于此目的:

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

for any power of 2, the following also holds.对于任何 2 的幂,以下也成立。

n&(-n)==n n&(-n)==n

NOTE: The condition is true for n=0 ,though its not a power of 2.注意:条件对 n=0 成立,尽管它不是 2 的幂。
Reason why this works is:这样做的原因是:
-n is the 2s complement of n. -n 是 n 的 2s 补码。 -n will have every bit to the left of rightmost set bit of n flipped compared to n. -n 将使 n 的最右侧设置位左侧的每一位与 n 相比翻转。 For powers of 2 there is only one set bit.对于 2 的幂,只有一个设置位。

This is probably the fastest, if using GCC.如果使用 GCC,这可能是最快的。 It only uses a POPCNT cpu instruction and one comparison.它只使用一个 POPCNT cpu 指令和一个比较。 Binary representation of any power of 2 number, has always only one bit set, other bits are always zero.任何 2 的幂的二进制表示,始终只有一位设置,其他位始终为零。 So we count the number of set bits with POPCNT, and if it's equal to 1, the number is power of 2. I don't think there is any possible faster methods.所以我们用 POPCNT 计算设置位的数量,如果它等于 1,这个数字就是 2 的幂。我认为没有任何可能的更快的方法。 And it's very simple, if you understood it once:这很简单,如果你理解一次:

if(1==__builtin_popcount(n))

Following would be faster then most up-voted answer due to boolean short-circuiting and fact that comparison is slow.由于布尔短路和比较缓慢的事实,以下将比大多数投票的答案更快。

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

If you know that x can not be 0 then如果你知道 x 不能为 0 那么

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

What's the simplest way to test whether a number is a power of 2 in C++?在 C++ 中测试一个数字是否是 2 的幂的最简单方法是什么?

If you have a modern Intel processor with theBit Manipulation Instructions , then you can perform the following.如果您拥有带有Bit Manipulation Instructions的现代英特尔处理器,那么您可以执行以下操作。 It omits the straight C/C++ code because others have already answered it, but you need it if BMI is not available or enabled.它省略了直接的 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, and Clang signal BMI support with __BMI__ . __BMI__支持 GCC、ICC 和 Clang 信号 BMI。 It's available in Microsoft compilers in Visual Studio 2015 and above when AVX2 is available and enabled .AVX2 可用并启用时,它在 Visual Studio 2015 及更高版本的 Microsoft 编译器中可用 For the headers you need, see Header files for SIMD intrinsics .对于您需要的头文件,请参阅SIMD 内在函数的头文件

I usually guard the _blsr_u64 with an _LP64_ in case compiling on i686.我平时守卫_blsr_u64_LP64_的情况下,编制上的i686。 Clang needs a little workaround because it uses a slightly different intrinsic symbol nam: 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

Can you tell me a good web site where this sort of algorithm can be found?你能告诉我一个可以找到这种算法的好网站吗?

This website is often cited: Bit Twiddling Hacks .这个网站经常被引用: Bit Twiddling Hacks

return n > 0 && 0 == (1 << 30) % n;

This isn't the fastest or shortest way, but I think it is very readable.这不是最快或最短的方式,但我认为它非常易读。 So I would do something like this:所以我会做这样的事情:

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

This works since binary is based on powers of two.这是有效的,因为二进制基于 2 的幂。 Any number with only one bit set must be a power of two.任何只有一位设置的数字必须是 2 的幂。

Here is another method, in this case using |这是另一种方法,在这种情况下使用| instead of & :而不是&

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

It is possible through c++可以通过 C++

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

I know this is a very old post, but I thought it could be interesting to post this here.我知道这是一个老的帖子,但我认为在这里发布这个帖子会很有趣。


From Code-Golf SE (so all credit to the one(s) who wrote this): Showcase of Languages来自Code-Golf SE (所以都归功于写这篇文章的人): 语言展示

(Paragraph about C , subparagraph Length 36 snippet ) (关于C 的段落,分段长度 36 片段

bool is_pow_of_2(const unsigned long long &num){return!!num&!(num&(num-1));}

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

This is the bit-shift method in T-SQL (SQL Server):这是 T-SQL (SQL Server) 中的位移方法:

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

It is a lot faster than doing a logarithm four times (first set to get decimal result, 2nd set to get integer set & compare)它比做四次对数要快得多(第一组得到十进制结果,第二组得到整数集和比较)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++:在Windows上使用C ++读写BMP文件的最简单方法是什么? - C++: What's the simplest way to read and write BMP files using C++ on Windows? 在 C/C++ 中,反转字节中位顺序的最简单方法是什么? - In C/C++ what's the simplest way to reverse the order of bits in a byte? 在C ++中编写可移植动态可加载库的最简单方法是什么? - What's the simplest way to write portable dynamically loadable libraries in C++? 将数字提高到幂的 C++ 函数是什么? - What is the C++ function to raise a number to a power? 在 C/C++ 中编写计时器的最简单方法是什么? - What is the simplest way to write a timer in C/C++? 创建1个元素集的最佳\\最简单\\最快的方法是什么? (C ++) - What is the best\simplest\fastest way to create set of 1 element? (C++) 在c ++中将const char []转换为字符串的最简单方法是什么? - What is the simplest way to convert a const char[] to a string in c++ 在C ++中创建编辑框的最简单方法是什么 - what is the simplest way to create edit box in c++ 通过C ++代码使用WEKA最简单的方法是什么? - What is the simplest way to use WEKA through C++ code? 什么是在linux上c ++ / Qt中解雇和忘记线程的最简单方法? - What is the simplest way to fire and forget a thread in c++ / Qt on linux?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM