진법

Etc

0 views

1. 개요 및 정의

1.1 한 줄 요약

  • 특정 숫자를 몇 개의 기호로 표현하고 계산할지 규칙을 정하는 약속이며, 마치 우리가 숫자를 셀 때 10개(0~9)의 기호를 사용하는 것처럼 컴퓨터는 2개의 기호(0과 1)만을 사용하도록 정한 규칙이다.

1.2 공식 정의

  • 진법(Radix or Base)은 숫자를 표기하는 방법의 집합으로, 특정한 수 r개를 묶어 상위 자릿수로 올리는 방식(r진법)을 의미한다.
    • 여기서 r을 기수(Radix 또는 Base)라고 부른다.
    • 일반적으로 n진법의 수는 n개의 기호(통상적으로 0부터 n-1)를 사용하여 값을 표현한다.
    • 7진법은 0~6 까지로 나타낸다.

2. 동작 원리

2.1. 자릿값의 원리 (Positional Notation)

  • 모든 진법은 위치적 기수법(Positional Notation)에 기반하며, 각 자릿값이 기수의 거듭제곱에 비례하여 증가한다.
    • 숫자의 위치가 그 숫자의 실제 value 를 결정한다는 것이다.
  • 예시1 - 2진수
    • 2진수 (101)2(101)_2(101)2를 자릿값 원리로 분해하면 다음과 같다.
    • 기수가 10이 아닌 2가 된다.
자리 위치 (Index)2 (22)1 (21)0 (20)
자릿값 (Weight)421
해당 숫자 (Digit)101
실제 값1 X 40 X 21 X 1

2.2 r진법 수의 표현

  • r진법으로 표현된 수 (dndn1d1d0)r (d_n d_{n-1} \dots d_1 d_0)_r(dndn1d1d0)r 의 실제 값은 다음과 같이 계산된다.

    Value=dnrn+dn1rn1++d1r1+d0r0\text{Value} = d_n \cdot r^n + d_{n-1} \cdot r^{n-1} + \dots + d_1 \cdot r^1 + d_0 \cdot r^0Value=dnrn+dn1rn1++d1r1+d0r0

    • did_idi: i번째 자릿수의 숫자 (항상 0di<r0 \le d_i < r0di<r를 만족해야 한다).
    • rir^iri: i번째 자릿값의 가중치(Weight).

2.3 예시: 10진법

(123)10=1102+2101+3100=100+20+3=123(123)_{10} = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0 = 100 + 20 + 3 = 123(123)10=1102+2101+3100=100+20+3=123

2.4 컴퓨터와 주요 진법

  • 컴퓨터 과학에서는 주로 2진법, 8진법, 16진법을 사용한다.
진법 (Base)이름사용 기호주요 용도
2진법 (Binary)Base 20, 1컴퓨터의 내부 연산 및 데이터 저장 (트랜지스터의 ON/OFF 상태)
8진법 (Octal)Base 80 ~ 7유닉스 파일 권한(rwx=4+2+1\text{rwx} = 4+2+1rwx=4+2+1) 표현
10진법 (Decimal)Base 100 ~ 9인간이 일상생활에서 사용
16진법 (Hexadecimal)Base 160 ~ 9, A ~ F메모리 주소, 색상 코드(RGB), 데이터 바이트 표현

3. 진법 변환 원리

3.1 r진수 \rightarrow 10진수

  • 각 자릿값에 rir^iri의 가중치를 곱하여 모두 더한다 (위의 2.1. 자릿값의 원리 참조).
  • 예시 1: 2진수를 10진수로 변환
    • 문제: (1101)2(1101)_2(1101)2 를 10진수로 바꾸면
      1. 자릿값 나열: 오른쪽 끝부터 20,21,22,232^0, 2^1, 2^2, 2^320,21,22,23 순서다.
        1. 1×23=1×8=81 \times 2^3 = 1 \times 8 = 81×23=1×8=8
        2. 1×22=1×4=41 \times 2^2 = 1 \times 4 = 41×22=1×4=4
        3. 0×21=0×2=00 \times 2^1 = 0 \times 2 = 00×21=0×2=0
        4. 1×20=1×1=11 \times 2^0 = 1 \times 1 = 11×20=1×1=1
      2. 모두 더하기: 8+4+0+1=138 + 4 + 0 + 1 = \mathbf{13}8+4+0+1=13
    • 문제: 16진수를 10진수로 변환
      1. 자릿값 나열: 오른쪽 부터 160,16116^0, 16^1160,161 순서다.
        1. 2×161=2×16=322 \times 16^1 = 2 \times 16 = 322×161=2×16=32
        2. F×160=15×1=15F \times 16^0 = 15 \times 1 = 15F×160=15×1=15
      2. 모두 더하기: 32+15=4732 + 15 = \mathbf{47}32+15=47

3.2 10진수 r\rightarrow rr진수

  • 10진수를 r로 나누고 남은 나머지(Remainder)를 역순으로 읽는다.
    • 단계 1: 10진수를 r로 나눈다.
    • 단계 2: 그 나머지가 r진수의 가장 낮은 자릿값(LSB)이 된다.
    • 단계 3: 몫을 다시 r로 나누고, 그 나머지가 다음 자릿값이 된다.
    • 단계 4: 몫이 0이 될 때까지 반복한다.

예시: (13)102 (13)_{10} \rightarrow 2(13)102진법

  1. 13÷2=6113 \div 2 = 6 \dots \mathbf{1}13÷2=61
  2. 6÷2=306 \div 2 = 3 \dots \mathbf{0}6÷2=30
  3. 3÷2=113 \div 2 = 1 \dots \mathbf{1}3÷2=11
  4. 1÷2=011 \div 2 = 0 \dots \mathbf{1}1÷2=01

결과: (1101)2(1101)_2(1101)2

3.3 2진수 \leftrightarrow 8진수/16진수

  • 2의 거듭제곱 진법 간의 변환은 그룹화를 통해 간단하게 이루어진다.
    • 2진수 \leftrightarrow 8진수 (Base 232^323): 2진수 3자리를 묶어 8진수 1자리로 변환한다.
    • 2진수 \leftrightarrow 16진수 (Base 242^424): 2진수 4자리를 묶어 16진수 1자리로 변환한다.
  • 예시: 2진수 (11010)2(11010)_2 \rightarrow(11010)2 8진수로 변환
    • 8진수 한 자리는 0~7 (231)(2^3-1)(231)까지 표현 가능하므로, 2진수 3비트와 정확히 매칭된다.
      1. 뒤에서부터 3자리씩 끊기: 11 | 010
      2. 앞자리 0 채우기 (Padding): 011 | 010 (3자리를 맞추기 위해 앞에 0 추가)
      3. 각 묶음을 변환:
        1. 0111+2=3011 \rightarrow 1+2 = \mathbf{3}0111+2=3
        2. 0100+2+0=2010 \rightarrow 0+2+0 = \mathbf{2}0100+2+0=2
      4. 결과 합치기: (32)8(32)_8(32)8
  • 예시: 2진수 (101110)2(101110)_2 \rightarrow(101110)2 16진수로 변환
    • 16진수 한 자리는 0~15 (241)(2^4-1)(241)까지 표현 가능하므로, 2진수 4비트와 매칭된다.
      1. 뒤에서부터 4자리씩 끊기: 10 | 1110
      2. 앞자리 0 채우기: 0010 | 1110
      3. 각 묶음을 변환:
        1. 001020010 \rightarrow \mathbf{2}00102
        2. 11108+4+2+0=1416진수기호E1110 \rightarrow 8+4+2+0 = 14 \rightarrow 16진수 기호 E11108+4+2+0=1416진수기호E
      4. 결과 합치기: (2E)16(2E)_{16}(2E)16

4. 실수의 표현 및 변환

  • 정수 부분이 r0,r1r^0, r^1r0,r1로 커지는 것과 달리, 소수점 이하는 r1,r2r^{-1}, r^{-2}r1,r2 형태로 작아진다.

4.1 소수점이 포함된 2진수 → 10진수

  • 자릿값(Weight)인 0.5(21),0.25(22),0.125(23)0.5(2^{-1}), 0.25(2^{-2}), 0.125(2^{-3})0.5(21),0.25(22),0.125(23)을 더한다.
    • (0.101)2=(1×0.5)+(0×0.25)+(1×0.125)=0.625(0.101)_2 = (1 \times 0.5) + (0 \times 0.25) + (1 \times 0.125) = \mathbf{0.625}(0.101)2=(1×0.5)+(0×0.25)+(1×0.125)=0.625

4.2 소수점이 포함된 10진수 → 2진수

  • 소수 부분에 2를 곱하고 정수 부분을 취하는 과정을 반복한다.
    • 예시: 0.687520.6875 \rightarrow 20.68752진수
      • 0.6875×2=1.3751취함,0.375남음0.6875 \times 2 = \mathbf{1}.375 \rightarrow 1 취함, 0.375 남음0.6875×2=1.3751취함,0.375남음
      • 0.375×2=0.750취함,0.75남음0.375 \times 2 = \mathbf{0}.75 \rightarrow 0 취함, 0.75 남음0.375×2=0.750취함,0.75남음
      • 0.75×2=1.51취함,0.5남음0.75 \times 2 = \mathbf{1}.5 \rightarrow 1 취함, 0.5 남음0.75×2=1.51취함,0.5남음
      • 0.5×2=1.01취함,0.0종료0.5 \times 2 = \mathbf{1}.0 \rightarrow 1 취함, 0.0 종료0.5×2=1.01취함,0.0종료
    • 결과: (0.1011)2(0.1011)_2(0.1011)2

5. 음수의 표현

  • 컴퓨터는 뺄셈 회로 없이 덧셈 회로만으로 뺄셈을 처리하기 위해 '2의 보수(Two's Complement)' 방식을 표준으로 사용한다.

5.1 부호 비트 (MSB, Most Significant Bit)

  • 0: 양수 (+)
  • 1: 음수 (-)
  • 데이터의 가장 왼쪽 비트(MSB)를 부호를 나타내는 용도로 사용한다.

5.2 2의 보수 변환 알고리즘

  • 음수 -N을 표현하기 위해 양수 N을 변환하는 단계는 다음과 같다.
    1. 1의 보수 (Invert): 모든 비트를 반전시킨다. (01,10)(0 \rightarrow 1, 1 \rightarrow 0)(01,10)
    2. 2의 보수 (Add 1): 결과에 1을 더한다.

5.3 변환 예시: -5 만들기 (8비트 기준)

  • 양수 5 표현: 0000 0101
  • 비트 반전: 1111 1010 (1의 보수)
  • 1 더하기: 1111 1011 (2의 보수)
    • 최종 결과: 1111 1011이 컴퓨터가 인식하는 -5이다.
0000 0101   (10진수 5)
 +  1111 1011   (10진수 -5, 2의 보수 형태)
 ---------------------------------------
(1) 0000 0000   (결과: 0)
 └── Overflow (버림): 8비트 범위를 벗어난 최상위 비트(Carry)는 무시된다.

6. 사용법 및 구문 (Syntax)

  • 프로그래밍 언어에서는 진법을 명시하기 위한 접두사(Prefix)를 사용한다.

6.1. C/C++, Java 등 주요 언어의 표기법

진법접두사예시설명
10진법없음 (기본)int a = 10;일반적인 정수 표기이다.
2진법0b 또는 0Bint b = 0b1010;10진수 10과 같다.
8진법0int c = 012;10진수 10과 같다
16진법0x 또는 0Xint d = 0xA;10진수 10과 같다.

6.2. 코드 예시

# 10진수
decimal_num = 255

# 2진수 표기
binary_num = 0b11111111
print(f"2진수 0b11111111은 10진수로 {binary_num}이다.") 
# 출력: 255

# 16진수 표기
hex_num = 0xFF
print(f"16진수 0xFF는 10진수로 {hex_num}이다.")
# 출력: 255

# 진법 변환 함수
print(f"255를 2진수로: {bin(255)}") # '0b' 접두사 포함 문자열로 반환
print(f"255를 8진수로: {oct(255)}") # '0o' 접두사 포함 문자열로 반환
print(f"255를 16진수로: {hex(255)}") # '0x' 접두사 포함 문자열로 반환

Loading comments...