컴퓨터 산술: 엔디언과 IEEE 754의 비밀
대부분의 프로그래머에게 숫자는 그저 float나 int일 뿐입니다. 하지만 표면 아래에서 컴퓨터가 이러한 값을 저장하고 조작하는 방식은 아키텍처별 선택과 뛰어난 수학적 절충으로 가득 찬 복잡한 세계입니다.
이 가이드에서는 메모리의 바이트 순서부터 종종 간과되는 비정규 수(Subnormal Numbers)를 포함한 IEEE 754 표준의 정교한 수학에 이르기까지 저수준 데이터 표현을 탐구합니다.
1. 순서의 문제: 엔디언(Endianness)
32비트 정수 0x12345678이 있다고 가정해 보겠습니다. 이 숫자는 0x12, 0x34, 0x56, 0x78의 네 바이트로 구성됩니다. 이 바이트들은 컴퓨터 메모리에 어떻게 저장되어야 할까요?
빅 엔디언(Big-Endian, 직관적인 순서)
빅 엔디언 시스템에서는 "큰 끝"(가장 중요한 바이트)이 가장 낮은 메모리 주소에 저장됩니다.
주소 0: 0x12주소 1: 0x34주소 2: 0x56주소 3: 0x78
리틀 엔디언(Little-Endian, X86 표준)
대부분의 현대식 PC와 스마트폰에서 사용되는 리틀 엔디언 시스템에서는 "작은 끝"이 먼저 저장됩니다.
주소 0: 0x78주소 1: 0x56주소 2: 0x34주소 3: 0x12
왜 이것이 중요한가? 네트워크 바이트 순서
네트워크를 통해 데이터를 보낼 때 컴퓨터마다 엔디언이 다를 수 있습니다. 이를 해결하기 위해 인터넷 프로토콜은 네트워크 바이트 순서를 빅 엔디언으로 정의합니다. 저수준 네트워킹 코드를 작성할 때마다 전송 전에는 로컬 "호스트 바이트 순서"를 "네트워크 바이트 순서"로 변환하고, 수신 시에는 그 반대로 변환해야 합니다.
2. 부동 소수점 수학: IEEE 754
IEEE 754 표준은 부동 소수점 산술의 보편적인 언어입니다. 64비트 부동 소수점(double)은 세 부분으로 나뉩니다.
- 부호 비트 (1비트): 양수는 0, 음수는 1.
- 지수 (11비트): 숫자의 규모를 결정합니다.
- 가수/유효숫자 (52비트): 정밀도를 결정합니다.
지수 바이어스(Exponent Bias)
지수는 단순한 정수로 저장되지 않습니다. 대신 바이어스(double의 경우 1023)를 사용합니다. 이를 통해 11비트 필드로 지수 자체의 부호 비트 없이도 2의 양수 및 음수 거듭제곱을 모두 나타낼 수 있습니다.
유효숫자(Significand) vs 가수(Mantissa)
현대 IEEE 754에서는 유효숫자라는 용어를 사용합니다. 이는 "암시적 선행 비트"(보통 1)와 가수(실제로 저장되는 비트)로 구성됩니다. 첫 번째 비트를 1로 가정함으로써 한 비트의 공간을 절약하고 정밀도를 높일 수 있습니다.
3. 예외 상황: 비정규 수(Subnormal Numbers)
표준 부동 소수점에서는 선행 비트가 항상 1이라고 가정합니다. 하지만 0에 점점 더 가까워지면 어떻게 될까요?
0에서의 "간극"
비정규 수가 없다면 표현 가능한 가장 작은 양수와 0 사이에 큰 "간극"이 생길 것입니다. 이를 "언더플로우(Underflow)"라고 합니다.
비정규 수가 해결사
지수 필드가 모두 0일 때 IEEE 754 표준은 비정규 모드로 전환됩니다.
- 암시적 선행 비트는 1이 아닌 0이 됩니다.
- 이를 통해 숫자가 "부드럽게 언더플로우"되어 일반적인 경우보다 더 작은 값을 표현할 수 있습니다.
- 성능 비용: 많은 CPU에서 비정규 산술은 하드웨어의 메인 FPU가 아닌 마이크로코드에 의해 처리되므로 상당히 느려집니다. 오디오 처리나 게임과 같이 성능이 중요한 일부 소프트웨어는 이 성능 저하를 피하기 위해 "0으로 플러시(Flush to Zero, FTZ)"를 수행합니다.
4. 특수 값
- 무한대 (Inf): 지수는 모두 1, 가수는 모두 0.
- NaN (Not a Number): 지수는 모두 1, 가수는 0이 아님.
- 부호 있는 0 (-0.0): IEEE 754는 +0과 -0을 구분하며, 이는 조건부 체크에서 미묘한 버그로 이어질 수 있습니다.
결론
컴퓨터 산술을 이해하는 것은 고성능 엔진의 내부를 들여다보는 것과 같습니다. 엔디언에 필요한 바이트 스와핑부터 비정규 수의 섬세한 "언더플로우" 로직에 이르기까지, 이러한 저수준 세부 사항은 소프트웨어를 정확하고 효율적으로 만드는 기반입니다.
네트워크 프로토콜을 디버깅하든 물리 엔진을 최적화하든, IEEE 754의 비밀과 엔디언의 규칙을 기억하세요. 그것들은 여러분이 수행하는 모든 계산의 보이지 않는 토대입니다.