펌 ) Devpia VC++ 강좌 엘키(sunghun84)
C 프로그래머가 알아야할 것들 - Chapter 1. 진법

김성훈 (sunghun84@nate.com)

Chapter 1. 진법

(1) 왜 진법에 대하여 배워야 하는가?
(2) 2진법
(3) 8진법
(4) 16진법

(1) 왜 진법에 대하여 배워야하는가?

진법이 뭘까요? 바로 수를 세는 단위입니다.

진법중에는 우리가 흔히 사용하고 있는것은 60진법(초,분을 재는데에 쓰이는 방식. 0~59까지 세고, 60이 되었을떄 자리올림하는 수체계)이나, 10진법(0~9까지 세고, 10이 되었을 때는 자리올림을 하는 우리가 기본적으로 수를 세는방식)등도 있습니다.

그 중에서도 여기서 배울 것은 2진법,8진법,16진법이 있는데요, 이 진법들에 공통점은, 모두다 2진수와 연관이 있는 진법이라는 겁니다.

왜 2진수(혹은 2진수와 관련이 깊은 진법에 대해 알아야 될까요? 그 이유는 컴퓨터는 0과 1밖에 구분하지 못하기 때문입니다. 컴퓨터는 전류가 흐를 때, 흐르지 않을때를 통해 구분하는것으로써, 2진수와 일맥 상통하게 됩니다. 2진수는 또한 참과, 거짓으로 상태를 표기하는 부울대수와도 연관이 깊죠.

그런데 게임과, 메신져 이런것들이 0과 1만으로 실행 되는거라고? 거짓말 아냐? 라고 생각하실분들도 계실텐데요, 그것에 대해서는 2번째 챕터 비트의 법칙에서 자세히 설명하도록하겠습니다.

16진수는 2진수 매우 연관이 깊어 2진수를 4개 단위로 읽을 때 유용하게 이용되기도 합니다. 8진수는 16진수와 비슷하게 2진수를 3개 단위로 읽을 때 혹은, 10진수에서의 상호 변환등에서 자주 사용되게 됩니다.

또한, 컴퓨터는 수를 계산(연산)을 하는 기계입니다. 그렇기 때문에, 수를 표현하는 방식(그 중에서도 컴퓨터가 사용하는 2진수와 관련이 깊은)에 대해서 알아둬야할 필요가 있는 것입니다.

(2) 2진법

아까 언급했듯이, 컴퓨터는 0과 1밖에 수를 인식하지 못합니다.

2진수는 0과 1로써 수를 세는 방법입니다.

자리수가 2가 되었을때 자리 올림을 하여 10으로 표시하는 수체계죠.

2진수는 표현할 때

0011 (2)

위와같이 표현하곤합니다. 괄호는 반드시 써야하는건 아니고, 혼돈의 여지가 있을 때만 사용하곤합니다.

2진수
10진수

0000
0

0001
1

0010
2

0011
3

0100
4

0101
5

0110
6

0111
7

1000
8

1001
9

1010
10


위의 표를 보시면, 대강 어떤지 감이 오실겁니다.
10진수가 11일때 2진수로는 몇이 될까요?
네 그렇죠~ 1011이 되는겁니다.


그런데...2진수가 너무 읽기 힘들다구요?

8 4 2 1
1 0 0 1 (자릿수가 1일 때마다, 머리위에 위치한 수만큼 더해줍니다)



8에 위치한 2진수가 1이니 8, 4와 2자리에 위치한 수는 0이니 그냥 내버려두고, 1의 자리에 위치한 수가 1이니 1. 그래서 나온수인 8과 1을 더하면 9가 되는거죠. 쉽죠?

마찬가지로 이진수가 커질때에도

128 64 32 16 8 4 2 1
0 0 0 0 0 0 0 0

이런식으로, 수가 하나 증가할때마다 수가 배로 증가하게 됩니다. 이렇게 하니 2진수 읽는 법은 감이 오죠?


그런데...음수를 표현할땐 어떻게 해야 할까요?

-0011 이런식으론 안되냐구요?

아쉽게도, 10진수와는 달리 -부호를 사용할수 없습니다.

그래서 최상위 비트(가장 앞에 있는 수를 최상위 비트=MSB라 부르게 되죠. 비트란 다음 강좌에서 배우게 될 바이너리 디지트=이진수의 약자입니다)를 부호 비트로 사용하게 되는것이죠.

최상위 비트가 0이면 양수, 1이면 음수로 표현 하기로 했습니다.

0001은 1, 1001은 -1 이렇게 말이죠.


그런데 이것은 문제가 있습니다.

2진수의 계산이 힘들어진것이죠.

1001 + 0001 = 1010

(-1) (1) (0 이어야 함)



2진수의 덧셈에서 자리 올림수가 발생하면 일반 덧셈에서 자리 올림수와 마찬가지로 처리해주면 됩니다.

그건 그렇고, 뭔가 이상하죠? 1010이라니...최상위 비트가 1이니 음수인거 같고, 뒤가 010이니 -2인거 같은데... 어? 0이 아니네요?

그래서 나온 것이 1의 보수입니다.


1의 보수란, 음수 표현시에 0을 1로, 1을 영으로 모든 수를 반전 시키는것이죠.

1의 보수로 표현하자면,

0001은 1, 1110은 -1이 되는거죠.


자..아까 계산이 잘못되었던 -1에서 1을 더해볼까요?

1110 + 0001 = 1111

(-1) (1) (0이어야 함)

어? 여전히 뭔가 이상하죠?? 최상위 비트가 1이니 음수 인거 같고....111이라면 -7? 왜 또 0이 아니지? 또 문제가 있었습니다.


그래서 2의 보수란 것이 나오게 된것입니다.

2의 보수란 0을 1로, 1을 0으로 모두 바꿔준후에 1을 더하는 방법입니다.

0001은 1, 1111은 -1이되는것이죠.



그럼 다시...계속 잘못되었던계산인 -7에서 7을 더해봅시다.

1111 + 0001 = 10000

(-1) (1) (0이어야 함)

음...이번에도 최상위 비트가 1이군요. 그럼 음순가? 그런데 뒤가 0000이네요? 하지만 이 계산은 맞습니다. 맨앞에 초과된 1은 무시하기 때문입니다. 그래서 0000 즉 0이 되는것이죠.



왜 2의 보수가 사용되는지 아셨겠죠?

참고로 1의 보수의 또다른 문제점은 0이 두 개이기 때문입니다.

1111 1111과, 0000 0000 각각 음수 0 양수 0을 의미합니다.

이에 비해 2의 보수는 0000 0000은 당연히 0이고, 0의 1의 보수인 1111 1111에서 1을 더하면 1 0000 0000이 되고, 이때 초과된 1은 무시하게 되므로 0은 양수 0 하나만 남게 되는것이죠. 이로써 아까 -1에서 1을 더하는 계산에서의 초과된 1을 무시하는 이유도 함께 이해가 되시죠?



(3) 8진법

8진법이란 0~7로 수를 세는 방법입니다.

8진수는 자릿수가 7이 넘어 8이 되었을때는 자리 올림하여서, 10으로 표현하는 수체계입니다.

8진수를 표기할때

12 (8)

이런식으로 작은 괄호로 8을 붙여서 표현하곤 합니다. 2진수와 마찬가지로 꼭 표기해줄 필요는 없습니다.
C언어등의 고급 언어에서 사용시에는 0(숫자 0)을 붙여서 사용하죠.

아래 표를 보시면, 2진수, 8진수, 10진수의 관계를 아실수 있을겁니다.

2진수
8진수
10진수

0000
0
0

0001
1
1

0010
2
2

0011
3
3

0100
4
4

0101
5
5

0110
6
6

0111
7
7

1000
10
8

1001
11
9

1010
12
10




8진수는 그 자체적인 의미도 중요하지만, 2진수에서의 변환이 매우 편리하다는 장점이 있습니다.

바로 수를 세 개단위로 묶어서 표현하면 되는것이죠.



4 2 1
1 1 1 (7입니다)

8진수로 바꿀때는, 4+2+1=7이 되는거죠.



이런식으로

4 2 1 4 2 1
1 1 0 0 1 1

4+2=6 2+1=3

8진수로 63이 되는겁니다.


10진수 524을 8진수로 구해봅시다.

524 / 8 = 65 나머지 4

65 / 8 = 8 나머지 1

8 / 8 = 1 나머지 0

1 / 8 = 0 나머지 1

1014(8)

즉, 나머지를 역순으로 나열하면, 10진수에서, 8진수를 구할 수 있습니다.



다시 8진수 1014를 10진수로 바꿔봅시다.

1014(8) = 4 x 8에 0승 + 1 x 8에 1승 + 1 x 8에 3승
= 4 x 1 + 1 x 8 + 1 x 512
= 4 + 8 + 512
= 524

524(10)

각 자리수에 맞춰서 곱해주면, 8진수에서 10진수로 변환되는겁니다.


(4) 16진법

16진법이란, 수를 0부터 15로 세다가, 16이 되어 자리올림할땐 10으로 표현하는 방법을 말합니다.

그런데...뭔가 조금 이상하죠? 0~15로 수를 센다면, 0~9는 괜찮겠지만, 10부터 15는 자리 올림된 10~15와 같게 되니까요.

그래서 10~15는 A~F로 표현하게 됩니다.

16진수도 8진수 2진수와 마찬가지로,

AF (16)

위와 같이 표기할 수 있습니다.

C언어등 고급언어에서 16진수 표현시 숫자 앞에 0x (숫자 0과 알파벳 x)를 붙여서 사용합니다.


아래 표를 보시면 진법에 따른 수 표현 방식을 이해하실수 있을겁니다.

2진수
8진수
16진수
10진수

0000
0
0
0

0001
1
1
1

0010
2
2
2

0011
3
3
3

0100
4
4
4

0101
5
5
5

0110
6
6
6

0111
7
7
7

1000
10
8
8

1001
11
9
9

1010
12
A
10

1011
13
B
11

1100
14
C
12

1101
15
D
13

1110
16
E
14

1111
17
F
15


16진수도 8진수처럼 2진수에서의 변환이 쉽다고 했었죠?

16진수도 2진수를 8진수로 변환하는 것과 비슷합니다. 2진수 4개씩 묶어서 16진수로 변환하면 되는것이죠.

8 4 2 1
1 1 0 0 (12입니다)

8+4=12인데, 12는 알파벳 C로 표현하기로 했으니,

8+4=C로 표현할수 있는것이죠.

8 4 2 1 8 4 2 1
1 0 1 0 0 0 1 1

8+2=A 2+1=3

A3으로 4자리씩 묶어서 변환함으로써 2진수를 좀 더 읽기 쉽게 하는것이죠.

16진수는 또한 니블(Nibble)에 기본 단위가 됩니다. 니블이란 비트를 4개씩 묶어서 표현하는 방식으로써, 16진수와 같은 방식으로 표현할 수 있게 되죠.

이것으로 각 진법에 대하여 알아봤는데요, 2진수, 8진수, 16진수가 모두 연관이 있다는 것을 알수 있었습니다. 특히나 2진수는 어떤수로나 변환이 쉽다는 것도 말이죠.

+ Recent posts