이진수로 1의 개수 세기(C 언어)

목차

주제 개요

방법 1

방법 2

방법 3


주제 개요

정수 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;
}

시험

 

추천

출처blog.csdn.net/2301_76161469/article/details/131055280