목차
먼저 원본 코드의 역코드와 보수 코드를 살펴보겠습니다.
두 번째로, 시프트 연산자 << >>:를 살펴보겠습니다.
주제:
매개변수 바이너리에 있는 1의 개수를 반환하는 함수를 작성하세요.
예: 15 0000 1111 4 1
준비하다:
함수를 생성합니다:
#include<stdio.h>
int CountOne(int num)
{
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = CountOne(num);
printf("%d\n",ret);
return 0;
}
방법 1(양수에만 해당):
아이디어:
특정 수의 소수 매개변수를 계산하려면 모듈로 연산을 사용하여 매개변수 %10을 만들 수 있습니다.
따라서 매개변수의 마지막 자리를 구한 후 매개변수 /10을 계산하고 모듈로 연산을 수행하게 되는데...
바이너리에서도 같은 방법을 사용할 수 있습니다. 매개변수 %2를 허용해야 합니다.
매개변수의 마지막 숫자를 얻은 다음 매개변수/2를 허용하고 모듈로 연산을 수행할 수 있습니다...
먼저 십진수로 1의 개수를 세는 방법을 살펴보겠습니다.
int CountOne(int num)
{
int count = 0;
while (num)
{
if (num % 10 == 1)
{
count++;
}
num /= 10;
}
return count;
}
답변:
비유하자면, 이진수로 1의 개수를 세는 방법을 다음과 같이 쓸 수 있습니다.
int CountOne(int num)
{
int count = 0;
while (num)
{
if (num % 2 == 1)
{
count++;
}
num /= 2;
}
return count;
}
비교해 보면 %와 / 뒤의 숫자만 바뀌었다고 보는 것은 어렵지 않습니다. 마찬가지로 8진수에서도 특정 숫자의 개수를 이런 식으로 계산할 수 있습니다.
방법 2(양수 및 음수에 공통):
머리말:
먼저 원본 코드의 역코드와 보수 코드를 살펴보겠습니다.
두 번째로 시프트 연산자 << >>를 살펴보겠습니다.![](https://img-blog.csdnimg.cn/5ef7b12ed9b64da8834aee11afdd3f38.png)
물론 컴퓨터는 항상 정수의 보수를 이동합니다.
마지막으로 비트 연산자 & | ^를 살펴보겠습니다.
비트별 AND:
![](https://img-blog.csdnimg.cn/6a16bccf119c405a8287d99d25d71ab3.png)
비트 OR |:
비트별 XOR^:![](https://img-blog.csdnimg.cn/89dfd85df4004cb38a6281f0cc22e91e.png)
요약:
이를 알면 다음과 같은 작은 결론을 내릴 수 있습니다.
a&1=1 a|0=a a^0=a a^a=0
아이디어:
시프트 연산자를 통해 매개변수 바이너리의 각 비트를 찾아 각 비트의 결과가 1인지 확인할 수 있습니다.
답변:
매개변수를 매번 1비트씩 이동한 다음 1씩 비트 AND하여 그 값이 1인지 확인하는 것을 생각할 수 있지만, 시프트 연산자가 매개변수의 값을 변경하지 않는다는 것도 알고 있으므로 다음과 같이 할 수 있습니다. i 위치를 이동할 때마다 매개변수를 이동하고, i를 이동할 때마다 +1됩니다.
int CountOne(int num)
{
int count = 0;
for (int i = 0; i < 32; i++)
{
if ((num >> i) & 1)
count++;
}
return count;
}
방법 3(방법 2의 최적화)
아이디어:
두 번째 방법을 통해 언제든지 32번 반복된다는 것을 알 수 있는데 어떻게 최적화할 수 있을까요? 실제로 여기서는 매우 영리한 방법이 사용됩니다.
이진 시퀀스 n이 n-1이 되면 마지막 1은 0이 됩니다. n&(n-1)이면 마지막 숫자가 다르기 때문에 마지막 1은 0으로 변경되고 n이 0이 될 때까지 사이클이 반복됩니다. , 루핑을 중지하세요. 15를 예로 들어보겠습니다.
답변:
int CountOne(int num)
{
int count = 0;
while (num)
{
count++;
num = num & (num - 1);
}
return count;
}