N Log

정수를 2진수로 변환

문제

unsigned char 값을 2진수 문자열로 변환하시오.

풀이

2로 계속 나눈 뒤 뒤집기

#include <stdio.h>

void uchar_to_binary(unsigned char value, char result[9])
{
    unsigned char length = 0;

    if (value == 0)
    {
        result[0] = '0';
        result[1] = '\0';

        return;
    }

    while (value > 0)
    {
        result[length++] = (value % 2) + '0';
        value /= 2;
    }

    for (unsigned char i = 0; i < length / 2; i++)
    {
        char temp = result[i];
        result[i] = result[length - 1 - i];
        result[length - 1 - i] = temp;
    }

    result[length] = '\0';
}

int main(void)
{
    unsigned char number = 11;
    char binary[9];

    uchar_to_binary(number, binary);

    printf("%u -> %s\n", number, binary); // 1011

    return 0;
}

사람이 종이에 적어서 변환하는 바로 그 방법이다.
예를 들어 11을 2진수로 바꿀 때는 2로 계속 나누고 오른쪽에 나머지를 적는다.
2로 나누기 때문에 나머지는 제수보다 작은 0, 1 둘 중 하나가 된다.

2 ) 11 ... 1
2 )  5 ... 1
2 )  2 ... 0
2 )  1 ... 1
     0

계산이 끝난 후 나머지를 아래에서 위로 읽으면 2진수 1011이 완성된다.

코드도 같은 방식으로 value를 2로 나누면서 나머지를 result에 저장한다.
이때 나머지는 2진수의 오른쪽 끝자리부터 나오기 때문에 result에는 거꾸로 저장된다.
종이에 적은 나머지를 아래에서 위로 읽듯이, 저장된 문자열을 뒤집는다.
value가 0이면 나눗셈 반복문이 실행되지 않으므로 "0"을 직접 저장한다.

빈자리를 0으로 채우고 4자리마다 띄우기

#include <stdio.h>

void uchar_to_binary(unsigned char value, char result[10])
{
    unsigned char length = 0;
    char bits[8];

    while (value > 0)
    {
        bits[length++] = (value % 2) + '0';
        value /= 2;
    }

    while (length < 8)
    {
        bits[length++] = '0';
    }

    for (unsigned char i = 0; i < length / 2; i++)
    {
        char temp = bits[i];
        bits[i] = bits[length - 1 - i];
        bits[length - 1 - i] = temp;
    }

    unsigned char result_index = 0;

    for (unsigned char i = 0; i < length; i++)
    {
        result[result_index++] = bits[i];

        if ((i + 1) % 4 == 0 && i != length - 1)
        {
            result[result_index++] = ' ';
        }
    }

    result[result_index] = '\0';
}

int main(void)
{
    unsigned char number = 7;
    char binary[10];

    uchar_to_binary(number, binary);

    printf("%u -> %s\n", number, binary); // 0000 0111

    return 0;
}

앞의 풀이에서는 입력값이 7이면 111로 출력된다.
이번 풀이에서는 비어 있는 앞자리를 0으로 채우고 4자리마다 공백으로 구분한다.
그래서 7은 0000 0111로 출력된다.

앞의 풀이와 다른 점은 2로 나눈 뒤 8자리가 될 때까지 임시 배열 bits에 0을 채운다는 것이다.
어차피 값은 처음에 거꾸로 저장되고 나중에 뒤집히므로, 이 0들은 최종 결과의 앞자리를 채우게 된다.

그다음 bits에 저장된 문자를 하나씩 꺼내 result 배열에 옮긴다.
이 과정에서 4자리마다 공백을 추가하되, 마지막 4자리 뒤에는 공백이 필요 없으므로 현재 위치가 마지막 인덱스인지 함께 검사한다.

최상위 비트(MSB)부터 검사하기

#include <stdio.h>
#include <limits.h>

void uchar_to_binary(unsigned char value, char result[])
{
    for (unsigned char bit = sizeof(value) * CHAR_BIT; bit > 0; bit--)
    {
        unsigned char shift = bit - 1;
        unsigned char index = (sizeof(value) * CHAR_BIT) - bit;

        result[index] = (value & (1U << shift)) ? '1' : '0';
    }

    result[sizeof(value) * CHAR_BIT] = '\0';
}

int main(void)
{
    unsigned char number = 6;
    char binary[(sizeof(number) * CHAR_BIT) + 1];

    uchar_to_binary(number, binary);

    printf("%u -> %s\n", (unsigned int)number, binary); // 00000110
    return 0;
}

이 풀이에서는 최상위 비트(MSB)부터 최하위 비트(LSB)까지 각 비트를 차례대로 검사한다.
& 연산자로 각 위치의 비트가 1인지 확인한 뒤, 1이면 '1', 아니면 '0'result에 저장한다.