본문으로 건너뛰기

진법 변환

정보처리기사 목차프로그래밍 기초레슨 134 / 233

목차

진법은 수를 몇 가지 숫자로 적느냐로 나뉩니다. 2진법은 0과 1, 8진법은 0~7, 16진법은 0~9와 A~F(10~15)를 씁니다. 컴퓨터는 모든 값을 0과 1의 비트(bit)로 담고, 사람은 긴 2진수를 짧게 읽으려고 4비트씩 묶은 16진수와 3비트씩 묶은 8진수를 씁니다. 진법을 오가는 계산은 메모리 주소·IP 주소·해시 문제에 다시 나옵니다. 아래 그림은 10진수 26을 2로 나눈 나머지가 2진수가 되고, 비트를 넷씩·셋씩 묶어 16진수·8진수가 되는 모습입니다.

7단계 중 1단계. 2로 나눈다. 26을 몫이 0이 될 때까지 2로 나눕니다. 줄마다 나머지 0이나 1이 하나씩 나옵니다.

110진수를 2진수로 — 나머지를 거꾸로

10진수를 몫이 0이 될 때까지 2로 나누고, 나머지를 아래에서 위로 읽으면 2진수입니다.

나눗셈몫나머지
26 ÷ 2130
13 ÷ 261
6 ÷ 230
3 ÷ 211
1 ÷ 201

처음 나온 나머지가 맨 오른쪽 자리라 26은 11010입니다. 8진수·16진수도 8·16으로 나눠 나머지를 거꾸로 읽습니다. 어느 진법인지 밝힐 때는 (11010)₂처럼 밑을 작게 붙여 적습니다.

2자리 값 — n진수를 10진수로

오른쪽 끝이 1의 자리이고, 왼쪽으로 갈 때마다 밑(2·8·16)을 한 번씩 곱한 값이 자리 값입니다. 숫자마다 자리 값을 곱해 더하면 10진수가 됩니다.

진법자리 값(왼쪽으로 갈수록 큼)예
2진수… 16 · 8 · 4 · 2 · 111010 → 16 + 8 + 2 = 26
8진수… 512 · 64 · 8 · 1123 → 64 + 16 + 3 = 83
16진수… 4096 · 256 · 16 · 11A → 16 + 10 = 26

8진수 123을 83으로 바꾸는 계산이 이진 탐색과 해싱의 기수 변환법입니다.

3넷씩 묶어 16진수, 셋씩 묶어 8진수

16은 2⁴, 8은 2³이라, 2진수를 오른쪽 끝부터 넷씩 묶으면 16진수 한 자리, 셋씩 묶으면 8진수 한 자리가 됩니다. 모자라는 왼쪽 자리는 0으로 채웁니다.

  • 11010 → 0001 1010 → 1과 10(A) → 16진수 1A
  • 11010 → 011 010 → 3과 2 → 8진수 32

거꾸로 16진수는 한 자리를 2진수 네 자리로 풉니다. 3C는 0011 1100이고, A~F는 1010~1111입니다. 16진수끼리 더하다 한 자리가 16이 되면 그 자리에 0을 쓰고 윗자리로 1을 올립니다. 1C + 4는 C(12) + 4 = 16이라 20입니다.

4n비트로 나타내는 값 — 2ⁿ가지

비트 하나는 0과 1 두 가지라, n비트로는 0부터 2ⁿ − 1까지 2ⁿ가지 값을 나타냅니다.

비트 수값의 수쓰는 곳
42⁴ = 1616진수 한 자리
82⁸ = 2561바이트, IPv4 주소 한 칸(0~255)
102¹⁰ = 1,024크기 1,024인 페이지의 오프셋
162¹⁶ = 65,536IPv6 주소 한 칸(16진수 네 자리)

거꾸로 값 n가지를 가리려면 2ᵏ이 n 이상인 가장 작은 k비트가 있어야 합니다. 100가지는 2⁷ = 128이라 7비트입니다. 가상 메모리: 페이징과 세그먼테이션의 '아래 10비트'와 IP 주소와 IPv6의 16진수 칸이 이 셈입니다.

5C에서 진법 쓰기

C는 0x로 시작하는 상수를 16진수, 0으로 시작하는 상수를 8진수로 읽고, printf의 %o·%x·%X로 8진수·16진수를 찍습니다.

#include <stdio.h>

int main(void) {
  int n = 26;
  printf("%o %x %X\n", n, n, n);
  printf("%d %d\n", 032, 0x1A);
  return 0;
}
실행 결과
32 1a 1A
26 26

%x는 앞에 0x를 붙이지 않습니다. 010은 10이 아니라 8진수 10, 곧 8입니다.

예제

10진수 200을 2진수·16진수·8진수로

단계한 일결과
1200을 2로 나눈 나머지를 거꾸로 읽기11001000
2넷씩 묶기 — 1100 · 100016진수 C8
3셋씩 묶기 — 011 · 001 · 0008진수 310
4자리 값으로 확인 — 128 + 64 + 8200

Python으로 맞춰 봅니다.

n = 200
print(bin(n), oct(n), hex(n))
실행 결과
0b11001000 0o310 0xc8

같은 코드를 Java·Python으로

CJavaPython
8진수 상수0320320o32 — 032는 문법 오류
2진수 상수C23부터 0b110100b110100b11010
8진수·16진수로 찍기%o · %xprintf의 %o · %xoct(26)이 '0o32', hex(26)이 '0x1a'
16진수 글자를 수로—Integer.parseInt("1A", 16)int('1A', 16)

시험 포인트

  • 필기: 2·8·10·16진수를 서로 바꾸는 문제가 나옵니다. 10진수는 밑으로 나눈 나머지를 거꾸로 읽고, 2진수를 넷씩 묶으면 16진수, 셋씩 묶으면 8진수입니다. A~F는 10~15이고, n비트는 2ⁿ가지(2¹⁰ = 1,024)입니다.
  • 실기: 계산 결과를 문제가 정한 진법으로 씁니다(포인터와 16진수 출제 주제). 16진수 주소에 바이트 수를 더할 때는 16에서 올림합니다. C 코드에서는 0x·0으로 시작하는 상수와 %x·%o 출력을 그대로 읽습니다.

확인 문제

1. 서로 다른 값 300가지를 비트로 가리려면 적어도 몇 비트가 있어야 하나요?

  • ① 8비트
  • ② 9비트
  • ③ 10비트
  • ④ 300비트
정답

②입니다. 2⁸ = 256은 300보다 작고, 2⁹ = 512는 300 이상입니다.

  • ① 256가지까지만 가립니다. 44가지가 남습니다.
  • ③ 가릴 수는 있지만 가장 적은 비트가 아닙니다. 9비트로 됩니다.
  • ④ 값 하나에 비트 하나를 쓰는 셈입니다. n비트는 2ⁿ가지를 가립니다.

2. 10진수 44를 2진수, 16진수, 8진수로 차례로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

정답

받는 답: 2진수 101100 · 16진수 2C · 8진수 54

44를 2로 나누면 나머지가 0, 0, 1, 1, 0, 1 차례로 나오고, 거꾸로 읽어 101100입니다. 넷씩 묶으면 0010 1100이라 2C, 셋씩 묶으면 101 100이라 54입니다.

  • 틀리는 꼴 001101: 나머지를 위에서부터 읽었습니다. 처음 나온 나머지가 맨 오른쪽입니다.
  • 틀리는 꼴 16진수 B0: 왼쪽부터 넷씩 묶었습니다(1011 00). 묶음은 오른쪽 끝부터입니다.

3. 16진수 B7을 2진수로 풀어 10진수로 바꾸는 표입니다. (가)·(나)를 채우세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

16진수 자리B7
10진수 값117
2진수 네 자리(가)0111

10진수로는 (나)입니다.

정답

받는 답: (가) 1011 · (나) 183

B는 11이라 8 + 2 + 1로 1011입니다. 10진수는 11 × 16 + 7 = 183이고, 2진수 10110111을 자리 값으로 더해도 128 + 32 + 16 + 4 + 2 + 1 = 183입니다.

  • 틀리는 꼴 (나)에 18: 두 자리 값 11과 7을 더하기만 했습니다. 왼쪽 자리는 16을 곱합니다.
  • 틀리는 꼴 (나)에 117: B7을 11과 7을 이어 쓴 10진수로 읽었습니다. 16진수는 자리마다 16배입니다.

4. 다음 코드의 출력을 그대로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

#include <stdio.h>

int main(void) {
  int a = 017;
  int b = 0x1F;
  printf("%d %d\n", a, b);
  printf("%x %o\n", a + b, 8);
  return 0;
}
정답

받는 답:

실행 결과
15 31
2e 10

017은 0으로 시작하는 8진수라 8 + 7 = 15이고, 0x1F는 16 + 15 = 31입니다. 15 + 31 = 46은 16진수로 2e이고, 8은 8진수로 10입니다.

  • 틀리는 꼴 첫 줄 17 31: 017을 10진수로 읽었습니다. 앞의 0은 8진수 표시입니다.
  • 틀리는 꼴 둘째 줄 0x2e 10: %x가 0x를 붙인다고 봤습니다. 숫자만 찍습니다.

5. 4바이트 칸 둘이 주소 0x1FC부터 이어 있습니다. 둘째 칸의 주소를 16진수로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

정답

받는 답: 0x200

0x1FC에 4를 더합니다. C(12) + 4 = 16이라 그 자리는 0이 되고 1을 올리며, F(15) + 1 = 16이라 또 0이 되고 1을 올려 1 + 1 = 2가 됩니다.

  • 틀리는 꼴 0x1F10: C + 4 = 16을 16진수 10으로 바꿔 그 자리에 그대로 적었습니다. 한 자리는 F(15)까지라 16이 되면 0을 남기고 윗자리로 1을 올립니다.
  • 틀리는 꼴 0x1FD: 1바이트 다음 칸으로 셌습니다. 칸이 4바이트라 4를 더합니다.

처음이라면: C 언어 과목(준비 중)의 '2진수 · 16진수와 printf' 레슨에서 같은 규칙을 처음부터 천천히 봅니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

정보처리기사 목차로