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);
누구든지 내가 이것을 어떻게 쓸 수 있는지 제안 할 수 있습니까? 이런 종류의 알고리즘을 찾을 수있는 좋은 웹 사이트를 알려주시겠습니까?
(n & (n - 1)) == 0
최고 다. 그러나 n = 0에 대해 부정확하게 true를 반환하므로 가능하면 명시 적으로 확인하는 것이 좋습니다.
http://www.graphics.stanford.edu/~seander/bithacks.html 에는 이것을 포함하여 영리한 비트 트위들 링 알고리즘이 많이 있습니다.
2의 거듭 제곱은 하나의 비트 세트 (부호없는 숫자의 경우) 만 갖습니다. 같은 것
bool powerOfTwo = !(x == 0) && !(x & (x - 1));
잘 작동합니다. 2의 거듭 제곱보다 작은 것은 하위 비트에서 모두 1이므로 AND는 비트 단위로 0이어야합니다.
부호없는 숫자를 가정하고 있었기 때문에 == 0 테스트 (원래 잊고 있었지만 죄송합니다)가 적절합니다. 부호있는 정수를 사용하는 경우> 0 테스트를 원할 수 있습니다.
바이너리에서 2의 거듭 제곱은 다음과 같습니다.
1: 0001
2: 0010
4: 0100
8: 1000
항상 정확히 1 비트 세트가 있습니다. 유일한 예외는 부호있는 정수입니다. 예를 들어 값이 -128 인 부호있는 8 비트 정수는 다음과 같습니다.
10000000
따라서 숫자가 0보다 큰지 확인한 후 영리한 해킹을 사용하여 1 비트 만 설정되었는지 테스트 할 수 있습니다.
bool is_power_of_2(int x) {
return x > 0 && !(x & (x−1));
}
접근법 # 1 :
그것을 확인하기 위해 은밀하게 숫자를 2로 나눕니다.
시간 복잡도 : O (log2n).
접근법 # 2 :
비트 AND 바로 이전 숫자가있는 숫자는 0과 같아야합니다.
예 : Number = 8 Binary of 8 : 1 0 0 0 Binary of 7 : 0 1 1 1 그리고 두 숫자의 비트 단위 AND는 0 0 0 0 = 0입니다.
시간 복잡도 : O (1).
접근법 # 3 :
비트 별 XOR 이전 숫자를 가진 숫자는 두 숫자의 합이어야합니다.
예 : Number = 8 Binary of 8 : 1 0 0 0 Binary of 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
bool is_power_of_2(int i) {
if ( i <= 0 ) {
return 0;
}
return ! (i & (i-1));
}
2의 거듭 제곱에 대해 다음도 적용됩니다.
n & (-n) == n
참고 : 조건은 2의 거듭 제곱이 아니지만 n = 0에 대해 참입니다.
이것이 작동하는 이유는 다음과 같습니다.
-n은 n의 2s 보수입니다. -n은 n에 비해 가장 오른쪽에 설정된 비트의 왼쪽에있는 모든 비트를 뒤집습니다. 2의 거듭 제곱의 경우 한 세트 비트 만 있습니다.
return n > 0 && 0 == (1 << 30) % 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
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++?
If you have a modern Intel processor with the Bit Manipulation Instructions, then you can perform the following. It omits the straight C/C++ code because others have already answered it, but you need it if BMI is not available or enabled.
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__
. It's available in Microsoft compilers in Visual Studio 2015 and above when AVX2 is available and enabled. For the headers you need, see Header files for SIMD intrinsics.
I usually guard the _blsr_u64
with an _LP64_
in case compiling on i686. Clang needs a little workaround because it uses a slightly different intrinsic symbol 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.
In C++20 there is std::ispow2
which you can use for exactly this purpose if you don't need to implement it yourself:
#include <bit>
static_assert(std::ispow2(16));
static_assert(!std::ispow2(15));
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. Any number with only one bit set must be a power of two.
This is the fastest:
if(1==__builtin_popcount(n))
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++
int IsPowOf2(int z) {
double x=log2(z);
int y=x;
if (x==(double)y)
return 1;
else
return 0;
}
Another way to go (maybe not fastest) is to determine if ln(x) / ln(2) is a whole number.
This is the bit-shift method in 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)
'developer tip' 카테고리의 다른 글
MVC3 Razor DropDownListFor 열거 형 (0) | 2020.09.17 |
---|---|
Android : 클릭시 임의의 색상 생성? (0) | 2020.09.17 |
루프없이 레코드를 유지하면서 배열에서 빈 문자열을 제거 하시겠습니까? (0) | 2020.09.17 |
디버깅을 시작할 수 없습니다. (0) | 2020.09.17 |
JavaScript에서 단어를 자르지 않고 문자열 단축 (0) | 2020.09.17 |