숫자가 2의 거듭 제곱인지 확인하는 방법


584

오늘 저는 숫자가 2의 거듭 제곱인지 확인하는 간단한 알고리즘이 필요했습니다.

알고리즘은 다음과 같아야합니다.

  1. 단순한
  2. 모든 ulong값을 정정하십시오 .

이 간단한 알고리즘을 생각해 냈습니다.

private bool IsPowerOfTwo(ulong number)
{
    if (number == 0)
        return false;

    for (ulong power = 1; power > 0; power = power << 1)
    {
        // This for loop used shifting for powers of 2, meaning
        // that the value will become 0 after the last shift
        // (from binary 1000...0000 to 0000...0000) then, the 'for'
        // loop will break out.

        if (power == number)
            return true;
        if (power > number)
            return false;
    }
    return false;
}

그러나 나는 정확히 둥근 숫자인지 확인하는 방법에 대해 생각했습니다 . 그러나 2 ^ 63 + 1을 확인하면 반올림으로 인해 정확히 63을 반환했습니다. 따라서 2의 거듭 제곱 63이 원래 숫자와 같은지 확인했습니다. 계산은 정확한 숫자가 아닌 s 로 수행되기 때문 입니다.log2 xMath.Logdouble

private bool IsPowerOfTwo_2(ulong number)
{
    double log = Math.Log(number, 2);
    double pow = Math.Pow(2, Math.Round(log));
    return pow == number;
}

true주어진 잘못된 값으로 돌아 왔습니다 : 9223372036854775809.

더 나은 알고리즘이 있습니까?


1
예를 들어 2의 거듭 제곱의 합 (x & (x - 1))이면 솔루션에서 오 탐지를 반환 할 수 있다고 생각합니다 . X8 + 16
Joe Brown

32
모든 숫자는 2의 거듭 제곱의 합계로 작성 될 수 있으므로 이진수로 숫자를 나타낼 수 있습니다. 또한 11000 & 10111 = 10000! = 0이므로 예제에서 오 탐지를 반환하지 않습니다.
vlsd

1
@JoeBrown 잘못된 긍정이 없습니다. 실제로이 표현은 2의 2 제곱의 합 중 더 큰 것을 반환합니다.
Samy Bencherif

답변:


1219

이 문제에 대한 간단한 트릭이 있습니다.

bool IsPowerOfTwo(ulong x)
{
    return (x & (x - 1)) == 0;
}

이 함수는 의 거듭 제곱이 아닌에 true대해 보고 합니다 . 제외하려면 다음과 같이하십시오.02

bool IsPowerOfTwo(ulong x)
{
    return (x != 0) && ((x & (x - 1)) == 0);
}

설명

가장 먼저 MSDN 정의의 비트 이진 및 연산자 :

이항 및 연산자는 정수 유형 및 부울에 대해 사전 정의됩니다. 정수 유형의 경우 &는 피연산자의 논리 비트 AND를 계산합니다. 부울 피연산자의 경우 &는 피연산자의 논리 AND를 계산합니다. 즉, 두 피연산자가 모두 참인 경우에만 결과가 참입니다.

이제이 모든 것이 어떻게 작동하는지 살펴 보겠습니다.

이 함수는 부울 (true / false)을 반환하고 unsigned long 유형 (이 경우 x)의 수신 매개 변수 하나를 허용합니다. 단순화를 위해 누군가가 값 4를 전달하고 다음과 같이 함수를 호출했다고 가정합니다.

bool b = IsPowerOfTwo(4)

이제 x의 각 항목을 4로 바꿉니다.

return (4 != 0) && ((4 & (4-1)) == 0);

글쎄, 우리는 이미 4! = 0이 참으로 사라지는 것을 알고있다. 그러나 어떻습니까 :

((4 & (4-1)) == 0)

이것은 물론 이것으로 번역됩니다.

((4 & 3) == 0)

그러나 정확히 무엇 4&3입니까?

4의 이진 표현은 100이고 3의 이진 표현은 011입니다 (&는이 숫자의 이진 표현을 기억합니다). 그래서 우리는 :

100 = 4
011 = 3

이 값들이 기본 덧셈과 매우 유사하게 쌓여 있다고 상상해보십시오. &연산자, 그렇지 않으면 0이다 따라서, 두 값이 모두 1과 같으면, 결과가 1 인 것을 말한다 1 & 1 = 1, 1 & 0 = 0, 0 & 0 = 0, 및 0 & 1 = 0. 그래서 우리는 수학을합니다 :

100
011
----
000

결과는 단순히 0입니다. 다시 돌아가서 return 문이 무엇을 의미하는지 살펴 보겠습니다.

return (4 != 0) && ((4 & 3) == 0);

이제 다음과 같이 번역됩니다.

return true && (0 == 0);
return true && true;

우리는 모두 그것이 true && true간단 하다는 것을 알고 있으며 true, 이것은 예에서 4가 2의 거듭 제곱임을 보여줍니다.


56
@Kripp : 숫자는 1000 ... 000 이진수 형식입니다. -1이면 0111 ... 111 형식입니다. 따라서, 초래 두 수의 바이너리와는 000000이 비 전력의-의 보수, 1,010,100 때문에 예를 들어 (계속 ...)의 결과로, 1,010,011 될 것이기 일어나지 않을 것입니다
피규

47
... 이진 후 1010000이 발생합니다. 유일한 오 탐지율은 0이므로 내가 사용하는 이유는 다음과 같습니다. return (x! = 0) && ((x & (x-1)) == 0);
구성자

6
Kripp, (2 : 1, 10 : 1) (4 : 3, 100 : 11) (8 : 7, 1000 : 111) (16:15, 10000 : 1111) 패턴을 보시겠습니까?
Thomas L Holaday

13
@ShuggyCoUk : 2의 보수는 음수가 표시되는 방식입니다. 이것은 부호없는 정수이므로 음수의 표현은 관련이 없습니다. 이 기술은 음이 아닌 정수의 이진 표현에만 의존합니다.
Greg Hewgill

4
@SoapBox-더 일반적인 것은 무엇입니까? 2의 거듭 제곱이 아닌 0 또는 0이 아닌 숫자? 이것은 더 이상의 상황이 없으면 대답 할 수없는 질문입니다. 그리고 정말, 정말 어쨌든 중요하지 않습니다.
구성자

97

이것과 다른 비트 트위들 링 해킹을 문서화하고 설명하는 일부 사이트는 다음과 같습니다.

그리고 그들의 할아버지, Henry Warren, Jr.의 "Hacker 's Delight"책 :

Sean Anderson의 페이지에서 설명하는 것처럼 이 표현 ((x & (x - 1)) == 0)은 0이 2의 거듭 제곱임을 잘못 표시합니다.

(!(x & (x - 1)) && x)

그 문제를 해결하기 위해.


4
0 2 ... 2 ^ -INF = 0의 전력이다)))
마이클 브레이

4
이것은 C # 태그 스레드 이기 때문에 !부울 유형에만 적용 할 수 있고 &&두 피연산자가 부울이어야합니다 (사용자 정의 연산자 제외). C #에서는 마지막 표현식 (Sean Anderson의)이 C #에서 유효하지 않다는 점을 지적 할 가치가 있습니다. 다른 것들을 가능하게하지만 그것은 관련이 없습니다 ulong.)
Jeppe Stig Nielsen

40

return (i & -i) == i


2
왜 이것이 작동하는지 또는 작동하지 않을지 힌트가 있습니까? 서명 된 ints / long 만있는 Java에서만 정확성을 검사했습니다. 맞다면 이것이 최고의 답이 될 것입니다. 더 빠르
거나

7
2의 보수 표기법의 속성 중 하나를 사용합니다. 숫자의 음수 값을 계산하려면 비트 단위 부정을 수행하고 결과에 1을 더합니다. 의 최하위 비트 i도 설정됩니다 -i. 그 아래의 비트는 0 (두 값 모두)이되고 그 위의 비트는 서로에 대해 반전됩니다. i & -i따라서 의 값은 최하위 설정 비트 i(2의 거듭 제곱)입니다. i동일한 값을 가진 경우 유일한 비트 세트입니다. i같은 이유로 0이면 실패합니다 i & (i - 1) == 0.
Michael Carman

6
경우 i서명되지 않은 유형 인,의 보수는 그것과는 상관이 없다. 당신은 단지 모듈 식 산술과 비트 단위의 속성을 이용합니다.
R .. GitHub 중지 지원 얼음

2
이 경우 작동하지 않습니다 i==0( (0&0==0)어느 것이 반환 됩니다 true). 그것은해야한다return i && ( (i&-i)==i )
bobobobo

22
bool IsPowerOfTwo(ulong x)
{
    return x > 0 && (x & (x - 1)) == 0;
}

3
음수를 입력 할 수 있으면 음수를 처리 할 수 ​​있기 때문에이 솔루션이 더 좋습니다. (ulong 대신 긴 경우)
Steven

이 경우 십진수가 2의 거듭 제곱으로 전달되는 이유는 무엇입니까?
chris Frisina


17

간단한 C ++ 솔루션 은 다음과 같습니다 .

bool IsPowerOfTwo( unsigned int i )
{
    return std::bitset<32>(i).count() == 1;
}

8
gcc에서 이것은이라는 단일 gcc 내장으로 컴파일됩니다 __builtin_popcount. 불행히도, 한 프로세서 제품군에는 아직 단일 어셈블리 명령어 (x86)가 없으므로 대신 비트 카운팅을위한 가장 빠른 방법입니다. 다른 아키텍처에서는 단일 어셈블리 명령어입니다.
deft_code

3
@deft_code 최신 x86 마이크로 아키텍처 지원popcnt
phuclv

13

허용되는 답변에 대한 다음 부록은 일부 사람들에게 유용 할 수 있습니다.

2의 거듭 제곱은 이진수로 표현 될 때 항상 1 처럼 보이고 n이 0 보다 크거나 같은 n 제로옵니다 . 예 :

Decimal  Binary
1        1     (1 followed by 0 zero)
2        10    (1 followed by 1 zero)
4        100   (1 followed by 2 zeroes)
8        1000  (1 followed by 3 zeroes)
.        .
.        .
.        .

등등.

1이러한 종류의 숫자에서 빼면 0이되고 n이 되고 다시 n이 위와 같습니다. 전의:

Decimal    Binary
1 - 1 = 0  0    (0 followed by 0 one)
2 - 1 = 1  01   (0 followed by 1 one)
4 - 1 = 3  011  (0 followed by 2 ones)
8 - 1 = 7  0111 (0 followed by 3 ones)
.          .
.          .
.          .

등등.

요점에 오기

우리가 x2의 거듭 제곱 인 숫자의 비트 AND를 수행하면 어떻게됩니까 x - 1?

하나는 x0으로 정렬 x - 1되고 모든 0은 x1로 정렬되어 x - 1비트 AND가 0이됩니다. 그리고 위에서 언급 한 단일 행 응답이 올바른 방법입니다.


위의 허용되는 답변의 아름다움에 더 추가-

그래서 우리는 지금 처분 할 재산이 있습니다 :

숫자에서 1을 빼면 이진 표현에서 가장 오른쪽 1이 0이되고 가장 오른쪽 1 이전의 모든 0이 1이됩니다.

이 속성을 가장 잘 사용하는 방법은 다음과 같습니다.- 주어진 숫자의 이진 표현에 몇 개의 1이 있습니까? 주어진 정수에 대해 짧고 달콤한 코드 x는 다음과 같습니다.

byte count = 0;
for ( ; x != 0; x &= (x - 1)) count++;
Console.Write("Total ones in the binary representation of x = {0}", count);

위에서 설명한 개념에서 증명할 수있는 숫자의 또 다른 측면은 "모든 양수를 2의 거듭 제곱의 합으로 나타낼 수 있습니까?"입니다..

예, 모든 양수는 2의 거듭 제곱의 합으로 표현할 수 있습니다. 예 : 숫자를 가져옵니다 117.

The binary representation of 117 is 1110101

Because  1110101 = 1000000 + 100000 + 10000 + 0000 + 100 + 00 + 1
we have  117     = 64      + 32     + 16    + 0    + 4   + 0  + 1

@ 미치 : 나는 0이 양수라고 어딘가에 주장 했습니까? 아니면 2의 거듭 제곱?
displayName

예, 예를 들어 0 을 넣고 이진 표현 내에서 수학을 작성하면됩니다. 혼란을 만듭니다.
Michi

1
두 숫자를 더하면 숫자가 양수 여야한다고 믿지 않게된다면 아무 것도 할 수 없습니다. 또한,이 숫자에서 2의 거듭 제곱을 건너 뛴다는 것을 나타 내기 위해 0이 도시되었다. 기본 수학을 아는 사람은 0을 추가하면 아무것도 추가되지 않는다는 것을 알고 있습니다.
displayName

10

질문을 게시 한 후 다음 해결책을 생각했습니다.

이진수 중 정확히 하나가 1인지 확인해야합니다. 따라서 숫자를 한 번에 한 자리 씩 오른쪽으로 이동하고 1과 true같으면 반환 합니다. 어느 시점에서든 홀수 ( (number & 1) == 1) 가 올 경우 결과는 false입니다. 이것은 (큰) 실제 값에 대한 원래 방법보다 약간 빠르며 (거의) 작은 값에 대해서는 훨씬 빠릅니다.

private static bool IsPowerOfTwo(ulong number)
{
    while (number != 0)
    {
        if (number == 1)
            return true;

        if ((number & 1) == 1)
            // number is an odd number and not 1 - so it's not a power of two.
            return false;

        number = number >> 1;
    }
    return false;
}

물론 Greg의 솔루션이 훨씬 좋습니다.


10
    bool IsPowerOfTwo(int n)
    {
        if (n > 1)
        {
            while (n%2 == 0)
            {
                n >>= 1;
            }
        }
        return n == 1;
    }

그리고 숫자가 다른 숫자의 거듭 제곱인지 알아내는 일반적인 알고리즘이 있습니다.

    bool IsPowerOf(int n,int b)
    {
        if (n > 1)
        {
            while (n % b == 0)
            {
                n /= b;
            }
        }
        return n == 1;
    }

6
bool isPow2 = ((x & ~(x-1))==x)? !!x : 0;

1
이것 c#입니까? 나는이 추측 c++으로 x부울로 반환됩니다.
Mariano Desanze

1
나는 그것을 C ++로 썼다. C #을 사소하게 만들려면 bool isPow2 = ((x & ~ (x-1)) == x)? x! = 0 : 거짓;
abelenky

4

주어진 숫자가 2의 거듭 제곱인지 확인하십시오.

#include <math.h>

int main(void)
{
    int n,logval,powval;
    printf("Enter a number to find whether it is s power of 2\n");
    scanf("%d",&n);
    logval=log(n)/log(2);
    powval=pow(2,logval);

    if(powval==n)
        printf("The number is a power of 2");
    else
        printf("The number is not a power of 2");

    getch();
    return 0;
}

또는 C #에서 return x == Math.Pow (2, Math.Log (x, 2));
구성자

4
부서진. 주요 부동 소수점 반올림 문제가 있습니다. 부동 소수점을 사용하려면 frexp불쾌한 log것 보다는 사용하십시오 .
R .. GitHub 중지 지원 얼음

4
bool isPowerOfTwo(int x_)
{
  register int bitpos, bitpos2;
  asm ("bsrl %1,%0": "+r" (bitpos):"rm" (x_));
  asm ("bsfl %1,%0": "+r" (bitpos2):"rm" (x_));
  return bitpos > 0 && bitpos == bitpos2;
}

4
int isPowerOfTwo(unsigned int x)
{
    return ((x != 0) && ((x & (~x + 1)) == x));
}

정말 빠릅니다. 모든 2 ^ 32 정수를 확인하는 데 약 6 분 43 초가 걸립니다.


4
return ((x != 0) && !(x & (x - 1)));

x2의 거듭 제곱 인 경우 고독한 1 비트가 위치에 n있습니다. 이는 x – 1위치가 0 임을 의미 n합니다. 왜 이진 뺄셈이 작동하는지 기억하십시오. 에서 1을 빼면 x차용이 모든 위치로 전파됩니다 n. 비트 n0이되고 이후의 모든 하위 비트는 지금 1.가 x함께 공통의 1 비트가없는 x – 1, x & (x – 1)0이며, !(x & (x – 1))사실이다.


3

1 세트 비트 만 포함하면 숫자는 2의 거듭 제곱입니다. 이 속성과 일반 함수 countSetBits를 사용하여 숫자가 2의 거듭 제곱인지 여부를 찾을 수 있습니다.

이것은 C ++ 프로그램입니다.

int countSetBits(int n)
{
        int c = 0;
        while(n)
        {
                c += 1;
                n  = n & (n-1);
        }
        return c;
}

bool isPowerOfTwo(int n)
{        
        return (countSetBits(n)==1);
}
int main()
{
    int i, val[] = {0,1,2,3,4,5,15,16,22,32,38,64,70};
    for(i=0; i<sizeof(val)/sizeof(val[0]); i++)
        printf("Num:%d\tSet Bits:%d\t is power of two: %d\n",val[i], countSetBits(val[i]), isPowerOfTwo(val[i]));
    return 0;
}

0을 False로 반환하기 때문에 0을 거듭 제곱 2로 명시 적으로 확인할 필요가 없습니다.

산출

Num:0   Set Bits:0   is power of two: 0
Num:1   Set Bits:1   is power of two: 1
Num:2   Set Bits:1   is power of two: 1
Num:3   Set Bits:2   is power of two: 0
Num:4   Set Bits:1   is power of two: 1
Num:5   Set Bits:2   is power of two: 0
Num:15  Set Bits:4   is power of two: 0
Num:16  Set Bits:1   is power of two: 1
Num:22  Set Bits:3   is power of two: 0
Num:32  Set Bits:1   is power of two: 1
Num:38  Set Bits:3   is power of two: 0
Num:64  Set Bits:1   is power of two: 1
Num:70  Set Bits:3   is power of two: 0

함수에 반환 유형이 'ulong'인 경우 c를 'int'로 반환합니까? 사용하여 while대신의 if? 나는 개인적으로 이유를 볼 수 없지만 효과가있는 것 같습니다. 편집 :-아니요 ... 0! 보다 큰 값은 1을 반환합니다 .
James Khoury 2012 년

@JamesKhoury 나는 C ++ 프로그램을 작성하고 있었으므로 int를 잘못 반환했습니다. 그러나 그것은 작은 오타였으며 공감대를받을 자격이 없었습니다. 그러나 나는 "if 대신 while을 사용하는 동안"과 "0보다 큰 것은 1을 반환합니다"라는 나머지 의견에 대한 추론을 이해하지 못합니다. 출력을 확인하기 위해 메인 스텁을 추가했습니다. AFAIK의 예상 출력입니다. 내가 틀렸다면 나를 바로 잡으십시오.
jerrymouse

3

다음은 내가 |대신 사용하여 고안 한 또 다른 방법 입니다 &.

bool is_power_of_2(ulong x) {
    if(x ==  (1 << (sizeof(ulong)*8 -1) ) return true;
    return (x > 0) && (x<<1 == (x|(x-1)) +1));
}

(x > 0)여기 비트 가 필요 합니까?
구성자

@configurator, 예, 그렇지 않으면 is_power_of_2 (0)은 true를 반환합니다
Chethan

3

2의 거듭 제곱에 대해 다음 사항도 적용됩니다.

n & (-n) == n

참고 : n = 0에 실패하므로 확인해야합니다.
이것이 작동 하는 이유는 다음과 같습니다.
-n은 n의 2의 보수입니다. -n은 n과 비교하여 n의 가장 오른쪽에있는 설정 비트의 왼쪽에있는 모든 비트를 뒤집습니다. 2의 거듭 제곱의 경우 하나의 세트 비트 만 있습니다.


2

0000 0001    Yes
0001 0001    No

연산

  1. 비트 마스크를 사용 NUM하여 변수를 이진으로 나눕니다 .

  2. IF R > 0 AND L > 0: Return FALSE

  3. 그렇지 않으면 NUM0이 아닌 값이됩니다.

  4. IF NUM = 1: Return TRUE

  5. 그렇지 않으면 1 단계로 이동하십시오.

복잡성

시간 ~ 이진수의 수는 O(log(d))어디 d입니까


1

비트 산술없이 @ user134548의 답을 개선합니다.

public static bool IsPowerOfTwo(ulong n)
{
    if (n % 2 != 0) return false;  // is odd (can't be power of 2)

    double exp = Math.Log(n, 2);
    if (exp != Math.Floor(exp)) return false;  // if exp is not integer, n can't be power
    return Math.Pow(2, exp) == n;
}

이것은 다음에 잘 작동합니다.

IsPowerOfTwo(9223372036854775809)

부동 소수점 연산은 단순한 비트 표현보다 훨씬 느립니다
phuclv

1

.NET Core 3, System.Runtime.Intrinsics.X86.Popcnt.PopCount 가있는 경우 Mark gravell이 제안 했습니다.

public bool IsPowerOfTwo(uint i)
{
    return Popcnt.PopCount(i) == 1
}

단일 명령으로 이동 속도는 빠르지 (x != 0) && ((x & (x - 1)) == 0)만 빠릅니다 .


당신은 그것이보다 빠르다고 확신 (x != 0) && ((x & (x - 1)) == 0)합니까? 나는 의심한다. popcnt를 사용할 수없는 구형 시스템에서
phuclv

더 빠르지 않습니다. 방금 현대 인텔 CPU에서 이것을 테스트하고 분해 (.NET이 아닌 C 코드로 부여)에서 사용되는 POPCNT를 확인했습니다. POPCNT는 일반적으로 비트 수를 계산하는 데 더 빠르지 만 단일 비트 온의 경우 비트 트위들 링 트릭이 여전히 10 % 빠릅니다.
eraoul

죄송합니다. 나는 분기 예측이 "속임수"라고 생각하면서 루프에서 테스트하고있었습니다. POPCNT는 실제로 단일 클럭 사이클에서 실행되는 단일 명령어이며 사용 가능한 경우 더 빠릅니다.
eraoul

0

C에서는 i && !(i & (i - 1)트릭을 테스트하고__builtin_popcount(i) 리눅스의 gcc와 -mpopcnt 플래그를 사용하여 CPU의 POPCNT 명령어를 사용하도록 . 내 테스트 프로그램은 2의 거듭 제곱 인 0과 2 ^ 31 사이의 정수 #을 세었습니다.

처음에는 i && !(i & (i - 1)POPCNT가 내가 사용한 분해에 사용되었음을 확인했지만 10 % 더 빠르다고 생각했습니다.__builtin_popcount .

그러나 if 문을 포함했으며 비트 트위들 링 버전에서 분기 예측이 더 잘 수행되고 있음을 깨달았습니다. 예상대로 if 및 POPCNT가 더 빨리 종료되었습니다.

결과 :

인텔 ® 코어 TM i7-4771 CPU 최대 3.90GHz

Timing (i & !(i & (i - 1))) trick
30

real    0m13.804s
user    0m13.799s
sys     0m0.000s

Timing POPCNT
30

real    0m11.916s
user    0m11.916s
sys     0m0.000s

AMD Ryzen Threadripper 2950X 16 코어 프로세서 최대 3.50GHz

Timing (i && !(i & (i - 1))) trick
30

real    0m13.675s
user    0m13.673s
sys 0m0.000s

Timing POPCNT
30

real    0m13.156s
user    0m13.153s
sys 0m0.000s

여기서 인텔 CPU는 비트 트위들 링으로 AMD보다 약간 느리지 만 POPCNT는 훨씬 빠릅니다. AMD POPCNT는 부스트를 제공하지 않습니다.

popcnt_test.c :

#include "stdio.h"

// Count # of integers that are powers of 2 up to 2^31;
int main() {
  int n;
  for (int z = 0; z < 20; z++){
      n = 0;
      for (unsigned long i = 0; i < 1<<30; i++) {
       #ifdef USE_POPCNT
        n += (__builtin_popcount(i)==1); // Was: if (__builtin_popcount(i) == 1) n++;
       #else
        n += (i && !(i & (i - 1)));  // Was: if (i && !(i & (i - 1))) n++;
       #endif
      }
  }

  printf("%d\n", n);
  return 0;
}

테스트를 실행하십시오.

gcc popcnt_test.c -O3 -o test.exe
gcc popcnt_test.c -O3 -DUSE_POPCNT -mpopcnt -o test-popcnt.exe

echo "Timing (i && !(i & (i - 1))) trick"
time ./test.exe

echo
echo "Timing POPCNT"
time ./test-opt.exe

0

많은 답변이 n &&! (n & (n-1))을 반환하도록 제안하고 있지만 입력 값이 음수이면 내 경험에 따라 잘못된 값을 반환합니다. 여기서 우리는 두 숫자의 거듭 제곱에 하나의 세트 비트 만 있다는 것을 알고 있기 때문에 또 다른 간단한 접근법을 공유 할 것입니다. 그래서 단순히 우리는 세트 비트의 수를 세어 O (log N) 시간이 걸립니다.

while (n > 0) {
    int count = 0;
    n = n & (n - 1);
    count++;
}
return count == 1;

이 기사를 확인하여 번호를 세십시오. 세트 비트


-1
private static bool IsPowerOfTwo(ulong x)
{
    var l = Math.Log(x, 2);
    return (l == Math.Floor(l));
}

번호 9223372036854775809로 시도하십시오. 작동합니까? 반올림 오류로 인해 생각하지 않습니다.
구성자

1
@configurator 922337203685477580_9_는 2의 거듭 제곱처럼 보이지 않습니다.)
Kirschstein

1
@ 키르 슈타인 (Kirschstein) : 그 숫자는 그에게 잘못된 긍정을 주었다.
Erich Mirabal

7
Kirschstein : 나에게는 하나도 보이지 않습니다. 그것은 기능에 하나처럼 보이지만 ...
구성자

-2

이 프로그램은 숫자가 2의 거듭 제곱 인 경우 "true"를 리턴하고 2의 거듭 제곱이 아닌 경우 "false"를 리턴합니다.

// To check if the given number is power of 2

import java.util.Scanner;

public class PowerOfTwo {
    int n;
    void solve() {
        while(true) {
//          To eleminate the odd numbers
            if((n%2)!= 0){
                System.out.println("false");
                break;
            }
//  Tracing the number back till 2
            n = n/2;
//  2/2 gives one so condition should be 1
            if(n == 1) {
                System.out.println("true");
                break;
            }
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in = new Scanner(System.in);
        PowerOfTwo obj = new PowerOfTwo();
        obj.n = in.nextInt();
        obj.solve();
    }

}

OUTPUT : 
34
false

16
true

1
이 질문은 C # 태그로 표시되며 귀하의 솔루션은 이전 솔루션에 비해 매우 느립니다 [
phuclv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.