십진수를 이진수로 바꾸는 연습문제

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h> //pow()
#include <string.h> // strlen()
#include <stdlib.h> // exit()
#include <stdbool.h>

unsigned char to_decimal(const char bi[]);
void print_binary(const unsigned char num);

int main()
{
	unsigned char i = to_decimal("01000110");
	unsigned char mask = to_decimal("00000101");

	print_binary(i);
	print_binary(mask);
	print_binary(i & mask);

	return 0;
}

unsigned char to_decimal(const char bi[])
{
	const size_t bits = strlen(bi);
	unsigned char sum = 0;
	for (size_t i = 0; i < bits; ++i)
	{
		if (bi[i] == '1')
			sum += (int)pow(2, bits - 1 - i);
		else if (bi[i] != '0')
		{
			printf("Wrong character : %c", bi[i]);
			exit(1);
		}

	}

	return sum;
}

void print_binary(const unsigned char num)
{
	printf("Decimal\\t %d\\t == Binary ", num);

	for (int i = 8; i >= 0; i--)
	{
		**int n = (int)pow((double)2, (double)i);**

		**if ((num & n) == n) //masking**
		{
			printf("1");
		}
		else if ((num & n) != n)
		{
			printf("0");
		}
		else
		{
			printf("error!\\n");
			exit(1);
		}
	}
	printf("\\n");

}

print_binary()를 구성하는 핵심 아이디어는

  1. 우리가 다루는 수들은 모두 내부적으로는 이진수로 구성되어있고, 논리연산자를 사용하면 해당 수를 이진수로 다룰 수 있다는 사실.
  2. masking이라는 아이디어 이용. &연산자는 동시에 1일때만 1을 반환함. 이를 이용해 해당 자리수가 1인지 0인지 구별 가능.

홍정모님의 코드를 보자.

void print_binary_hong(const unsigned char num)
{
	pritnf("Decimal %3d \\t== Binary ", num);

	const size_t bits = sizeof(num) * 8;
	for (size_t i = 0; i < bits; ++i)
	{
		**const unsigned char mask =
			(unsigned char)pow((double)2, (double)(bits - 1 - i));**

		if ((num & mask) == mask)
			printf("%d", 1);
		else
			printf("%d", 0);
	}
}

이 함수는 maks를 어떻게 구현할 것인가가 핵심인데, 난 이번엔 pow()내부를 간단하게 표현하고 싶어서 pow(2, i)를 한 대신, i를 8부터 감소하도록 했다.

홍정모님은 증가연산자를 사용하는 대신, pow(2, bits-1-i)를 또 이용했다.

또한 bits라는 변수를 하나 더 사용하심. 나는 그냥 정수 8을 for문 조건식에 주었지만… sizeof(num) * 8bits에 할당한 이유가 뭘까? num이 1byte(char type)이라서. 여기에 8을 곱해 8로 바꾼걸까..? 그냥 정수 8을 사용하는거랑 무슨 관련…? 아마 num이 1byte를 넘어가는 큰 숫자일때도 대응하기 위해서인가?

내가 만든것처럼 for문을 감소하는 형태로 만드는 경우를 설명하기 시작하심.

C++부터 size_t를 많이 사용한다. size_t자료형을 갖고 있는 i가 for문 내에서 감소연산자로 계속 감소하게 되면.. size_t는 기본적으로unsigned라서 조건문을 i≥0으로 해도 for문이 끝나지 않는 단점이 있다고 한다!

unsigned자료형은 0에서 -을 감소하면 오버플로우가 일어나버린다.

다음부터는 size_t를 사용하는 for문은 감소연산자를 사용하면 안된다! 라는 교훈 획득.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

비트단위 논리 연산자 확인해보기

우리가 구현한 print_binary()를 이용해 비트단위 논리연산자의 기능을 직접 확인해보자.