목차
주제 개요
정수 n이 주어지면 32비트 이진 표현에서 1의 개수를 출력하는 함수를 작성하세요(음수는 2의 보수로 표시됨).
방법 1
분석: 1234의 각 자릿수 합계를 계산할 때 각 자릿수에 대해 1234%10을 사용하여 4를 얻은 다음 1234/10을 사용하여 123을 얻은 다음 123% 10을 사용하는 방식입니다. 1234는 0이 됩니다.
같은 방식으로 정수의 각 이진 비트에 대해 %2,/2로 정수의 각 이진 비트를 얻을 수 있습니다.
코드는 아래와 같이 표시됩니다.
int NumberOf1(int n)
{
int count = 0;
while (n)
{
if (n % 2 == 1)
{
count++;
}
n /= 2;
}
return count;
}
시험
#include <stdio.h>
int NumberOf1(int n)
{
int count = 0;
while (n)
{
if (n % 2 == 1)
{
count++;
}
n /= 2;
}
return count;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = NumberOf1(n);
printf("%d的二进制中1的个数为%d", n, ret);
return 0;
}
시험 결과
그러나 입력된 정수가 음수이면 결과가 잘못됩니다.
-1의 보수는 1111111111111111111111111111111입니다.
그러나 결과는 0입니다. 디버깅을 통해 n이 -1일 때 n%2의 결과는 -1로 1이 아니며 카운트 값은 변경되지 않고 그대로 유지되는 것을 알 수 있습니다. 1/2은 0입니다. 이때 루프가 종료됩니다.
이 경우 unsigned int 유형을 사용하여 n을 받고 n을 부호 없는 정수로 변환 할 수 있습니다.
int NumberOf1(unsigned int n)
{
int count = 0;
while (n)
{
if (n % 2 == 1)
{
count++;
}
n /= 2;
}
return count;
}
다시 테스트하다
이번엔 결과가 맞았어
단, 이 메서드의 경우 수신 유형은 unsigned int 여야 합니다.
방법 2
n&1을 사용하면 n의 마지막 숫자를 얻은 다음 오른쪽으로 이동하여 비교된 숫자를 제거하고 다음 숫자를 얻고 32번 반복하여 이진수의 모든 숫자를 얻을 수 있습니다.
코드는 아래와 같이 표시됩니다.
int NumberOf1(int n)
{
int count = 0;
for (int i = 0; i < 32; i++)
{
//将n向右移动i位,再&1
if (((n >> i) & 1) == 1)
{
count++;
}
}
return count;
}
시험
그러나 이 방법의 경우 바이너리의 모든 비트를 꺼내려면 32번을 반복해야 합니다.
방법 3
n&(n-1)인 경우 n의 이진수에서 마지막 비트 1을 제거할 수 있습니다.
예를 들어
n = 10, 바이너리: 1010
n - 1개의 바이너리: 1001
n&(n-1) = 1000
n&(n-1)마다 이진수에서 1을 제거하고, n&(n-1)이 0일 때 n에서 1을 모두 제거합니다.
코드는 아래와 같이 표시됩니다.
int NumberOf1(int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
시험