0. 들어가며
우리가 일상에서 사용하는 숫자와 컴퓨터가 이해하는 숫자는 어떻게 다를까?
컴퓨터는 모든 정보를 0과 1로만 이해하는데, 어떻게 복잡한 수와 소수를 표현할 수 있을까?
컴퓨터의 자료 표현 방식에 대해 자세히 알아보자.
1. 기본 진법 변환
1.1 일상 vs 컴퓨터의 숫자 표현
우리는 보통 10진수를 사용하지만, 컴퓨터는 2진수를 기본으로 한다.
예를 들어 `123`이라는 숫자를 다양한 진법으로 표현하면:
- 16진수: 7B
- 10진수: 123 (우리가 사용하는 방식)
- 8진수: 173
- 2진수: 1111 011 (컴퓨터가 사용하는 방식)
1.2 2진수로 숫자 표현하기
컴퓨터가 숫자를 2진수로 표현하는 방법을 살펴보자.
정수 변환 예시:
- 13 = 8 + 4 + 1 → `1101`
- 각 자리는 2의 거듭제곱(8, 4, 2, 1)을 나타냄
소수 변환 예시:
- 0.75 = 0.5 + 0.25 → `0.11`
- 소수점 이하는 2의 음의 거듭제곱(0.5, 0.25, 0.125...)을 나타냄

1.3 실수의 2진수 표현 과정
정수부와 소수부 분리 변환
10진수 실수를 2진수로 변환할 때는 정수부와 소수부를 나누어 각각 변환
예시: 11.765625를 2진수로 변환
- 정수부 변환 (11 → 2진수)
- 11 ÷ 2 = 5 나머지 1
- 5 ÷ 2 = 2 나머지 1
- 2 ÷ 2 = 1 나머지 0
- 1 ÷ 2 = 0 나머지 1
- 결과: `1011`
- 소수부 변환 (0.765625 → 2진수)
- 0.765625 × 2 = 1.53125 → 정수부 1
- 0.53125 × 2 = 1.0625 → 정수부 1
- 0.0625 × 2 = 0.125 → 정수부 0
- 0.125 × 2 = 0.25 → 정수부 0
- 0.25 × 2 = 0.5 → 정수부 0
- 0.5 × 2 = 1.0 → 정수부 1
- 결과: `0.110001`
- 최종 결과: `1011.110001`
2진수 무한 소수 문제
모든 10진수 실수가 깔끔하게 2진수로 변환되는 것은 아님!
예시: 0.1을 2진수로 변환
- 0.1 × 2 = 0.2 → 0
- 0.2 × 2 = 0.4 → 0
- 0.4 × 2 = 0.8 → 0
- 0.8 × 2 = 1.6 → 1
- 0.6 × 2 = 1.2 → 1
- 0.2 × 2 = 0.4 → 0 (반복 시작!)
- ...
결과: `0.000110011001100...` (0011의 무한 반복!)
💡 팁: 소수의 끝이 5가 아닌 수를 2진수로 표현할 경우 대부분 무한 소수가 발생
이렇게 10진수에서 2진수로 소수를 변환하는 것은 많은 경우 정확한 변환이 불가능하며,
컴퓨터는 가장 근사한 값을 저장
→이것이 바로 부동소수점 오차의 근본 원인!
브라우저 콘솔창에서 `console.log(0.1 + 0.2);` 을 입력해보자.
console.log(0.1 + 0.2);
// 0.30000000000000004
console.log(0.1 + 0.2 === 0.3);
// false
2. 실수의 메모리 표현
컴퓨터 메모리는 2진수 체계를 기반으로 데이터를 저장하므로,
당연히 실수도 2진수로 표현해야 함.
정수에 비해 상대적으로 복잡하며, 대표적으로 두 가지 방식이 있음
2.1 고정 소수점(Fixed Point) 방식
동작 원리
메모리를 정수부와 소수부로 고정 분할하여 처리하는 방식

정수부가 15비트라면:
- `-2^15 ~ 2^15` 만큼의 정수만 표현
- 소수 부분까지 합친다면 `-2^15.xxx ~ 2^15.xxx` 범위를 표현
예시: 5.625를 고정 소수점으로 표현
- 2진수 변환
- 정수부: 5 → `101`
- 소수부: 0.625 → `0.101`
- 전체: `101.101`
- 메모리 할당 (32비트 가정: 부호 1비트, 정수부 15비트, 소수부 16비트)
부호 정수부 (15비트) 소수부 (16비트) 0 (0이면 양수, 1이면 음수) 00000000 0000101 10100000 00000000 - 정수 부분을 늘리면 소수 부분이 줄어들고, 소수 부분을 늘리면 정수 부분이 줄어들게 된다.
장단점 분석
✅ 장점:
- 직관적이고 구현이 단순함
- 연산 속도가 빠름
❌ 단점:
- 표현 범위 제한
- 32비트 기준으로 정수부 15비트 사용 시
- 최대 표현 가능한 수: 2^15 - 1 = 32,767
- 40000.01 같은 수는 표현 불가능! (정수부 15비트로 표현 불가능)
- 공간 낭비 심각
- 22777.12 표현 시 → 0.12라는 작은 소수를 위해 16비트 전체 사용
- 정수부가 큰 수와 소수부가 큰 수의 효율성 차이 극심
이러한 문제들 때문에 현대 컴퓨터는 부동 소수점 방식을 채택
2.2 부동 소수점 (Floating Point) 방식
IEEE 754 표준 구성
현재 컴퓨터의 표준으로, 소수점이 "떠다니는" 방식
IEEE 754표준:
- 1bit, 8bit, 23bit에 각각 부호, 지수, 가수를 할당하는 방법
32비트 구성:
- 부호 비트 (1비트): 양수(0), 음수(1)
- 지수 비트 (8비트): 수의 크기 범위 결정
- 가수 비트 (23비트): 수의 정밀도 결정

표현 방식 이해하기
예시: 263.3을 부동소수점으로 표현
- 2진수 변환: `100000111.010011001100110...`
- 정규화: 맨 앞 1 뒤로 소수점 이동
- `1.00000111010011001100110... × 2^8`
- 소수점을 이동시키는 것을 정규화(Normalization) 이라고 부른다.
- 정규화는 2진수를 `1.xxxx... X 2^n` 꼴로 변환하는 것
- 비트 할당:
- 부호: `0` (양수)
- 지수: `10000111` (127 + 8 = 135)
- 가수: `00000111010011001100110`
지수부의 bias
왜 127을 더할까?
- 우리가 알고 있는 `2^8`, `2^-3` 같은 지수는 양수/음수 다 있음
- 그런데 컴퓨터는 부호 없는 8비트로 지수만 저장하려고 함
- 그래서 음수 지수도 양수처럼 보이게 하기 위해 127을 더해서 저장하는 것!
그래서:
- 지수의 값은 2^(비트 수) 만큼 표현될 수 있음 (8비트 기준, 2^8 = 256)
- 그 범위를 절반으로 자르고, 0 한개를 제외한 값을 bias로 지정
- (8비트 기준) `(2^8 / 2) - 1 = 127`

단정밀도(single-precision)
- 32비트(1비트 부호, 8비트 지수, 23비트 가수)
- bias 고정값은 127이다.
배정밀도(double-precision)
- 64비트(1비트 부호, 11비트 지수, 52비트 가수)
- bias 고정값은 1023이다.
예시:
예: 우리가 표현하려는 실수
263.3 = 1.00000111... × 2^8 ← 지수가 8
그럼 지수 8을 저장해야 되는데, 지수 칸(8비트)은 0~255까지만 저장 가능
그래서...
지수 저장 값 = 실제 지수 + 127 = 8 + 127 = 135
즉, 지수 8을 표현하려면 135를 저장해야 함
이걸 2진수로 바꾸면:
135 = 1000 0111 (8비트)
이게 바로 지수 필드에 들어가는 값
즉:
| 실제 지수 | 저장 값 |
| -3 | 124 |
| 0 | 127 |
| 8 | 135 |
부동소수점의 효율성
// Java 타입 범위 비교
long maxLong = 9223372036854775808L;// 8바이트 정수형
float maxFloat = 3.4e38f;// 4바이트 실수형
System.out.println("Long 최대값: " + maxLong);
// 9,223,372,036,854,775,808
System.out.println("Float 최대값: " + maxFloat);
// 3.4 × 10^38
System.out.println("Float이 더 큰가? " + (maxFloat > maxLong));
// true!
놀라운 결과: 4바이트 float이 8바이트 long보다 훨씬 큰 범위를 표현
왜 이런 일이 가능할까?
- 고정 소수점의 한계
- 정수부(15비트) + 소수부(16비트)로 분할
- 각각 독립적으로 제한된 범위만 표현
- 부동 소수점의 효율성
- 가수부(23비트)에 실제 수의 값 저장
- 지수부(8비트)로 범위를 기하급수적으로 확장
- 정수부/소수부 구분 없이 전체 실수를 효율적 표현
부동 소수점의 한계
부동 소수점을 32비트, 64비트, 128비트 등..
비트 수를 더 늘려서, 실수를 더 정밀하게 표현할 수 있음
하지만, 무한소수처럼 부동 소수점의 표현법이나 2진수로 표현할 수 없는 값들도 존재

역으로 풀어보기
[ 0 10000010 0011011000000000]
가수부: 1.0011011 (생략된 1 포함)
편향된 지수값이 130이므로 실제 지수값은 3
즉, 1001.1011
결과 : 9.6875