본문 바로가기
Essays

[CS] 컴퓨터에서의 정수와 실수의 데이터 표현방법과 부동소수점

by VincentKim 2023. 4. 22.

1. 정수
컴퓨터는 정수를 이진수(binary) 형태로 저장합니다. 일반적으로 C/C++에서는 int형은 4바이트(32비트)를, long long 형은 8바이트(64비트)를 차지합니다. 

 

정수는 부호(sign)와 절댓값(magnitude)으로 나누어 저장됩니다. 부호는 양수와 음수를 구분하는 정보이며, 0 또는 1로 표현됩니다. 절댓값은 정수의 크기를 나타내며, 이진수로 변환된 값을 2진수로 저장합니다.

 


컴퓨터는 일반적으로 2의 보수(two's complement) 방식을 사용하여 정수를 저장합니다. 이 방식은 부호를 포함한 절댓값을 2진수로 변환한 후, 양수와 음수를 구분하지 않고 덧셈 연산을 수행할 수 있도록 구현된 방식입니다.

2. 실수


컴퓨터는 실수를 부동소수점(floating-point) 방식으로 저장합니다. 부동소수점 방식은 소수점의 위치를 고정하지 않고, 지수와 가수를 이용하여 실수를 표현하는 방식입니다. 일반적으로 C/C++에서는 float형은 4바이트(32비트)를, double형은 8바이트(64비트)를 차지합니다.

Java, Javascript, Python 도 IEEE 754 방식을 사용합니다. 출처:얄코 youtube

IEEE 754는 컴퓨터에서 부동소수점을 표현하는 방법을 표준화한 규격입니다. 이 표준은 IEEE(전기전자기술자협회)에서 1985년에 제정되었으며, 현재 대부분의 컴퓨터 시스템에서 부동소수점을 표현하는 데 사용됩니다.


IEEE 754는 32비트와 64비트 부동소수점을 표현할 수 있으며, 각각을 single precision(단정밀도)와 double precision(배정밀도)라고 부릅니다. 이 규격은 부호 비트, 지수 부분, 가수 부분으로 구성되며, 부호 비트는 0 또는 1의 값을 가지며, 양수와 음수를 구분합니다.

지수 부분은 부동소수점 값의 크기를 표현하며, 가수 부분은 실제 값의 유효 숫자를 저장합니다. 지수와 가수 부분은 2진수로 표현되며, 가수 부분은 정규화(normalization)된 형태로 저장됩니다. 이때, 정규화란 가수 부분에서 첫 번째 비트를 1로 고정하고, 나머지 비트는 소수점 아래의 값을 표현하는 것을 의미합니다.

IEEE 754 표준에서는 특별한 값인 NaN(Not a Number), 무한대(Infinity) 등도 표현할 수 있습니다. 또한, 이 표준은 부동소수점 값의 연산도 규정합니다. 이때 연산에서 발생하는 오차를 최소화하기 위해, 연산을 할 때마다 가장 정밀한 값을 유지하도록 반올림(rounding) 처리를 해야 합니다.

따라서, IEEE 754는 컴퓨터에서 부동소수점 값을 표현하고 처리하는 방식을 표준화하여, 서로 다른 시스템 간에도 부동소수점 값을 정확하게 전달하고 연산할 수 있도록 합니다.

하지만 부동소수점 방식에서는 이진수로 정확하게 표현할 수 없는 일부 실수 값들이 발생합니다. 예를 들어 0.1은 2진수 표현시 무한소수가 되어 정확하게 표현할 수 없기 때문에 근사값으로 표현됩니다. 

3. 오차 발생 이유
부동소수점 방식에서 오차가 발생하는 이유는 크게 두 가지입니다.

첫째, 부동소수점 방식에서는 표현 가능한 실수의 범위가 유한합니다. 이진수로 변환된 지수와 가수는 한정된 비트 수를 갖기 때문에, 표현 가능한 실수 값의 범위도 한정됩니다. 따라서 일부 실수 값들은 근사값으로 저장되어 오차가 발생할 수 있습니다.

둘째, 부동소수점 방식에서는 연산 중에도 근사값을 사용하기 때문에, 연산 과정에서도 오차가 발생할 수 있습니다. 특히 연산 과정에서 근사값의 오차가 누적되면, 결과값의 오차가 커질 수 있습니다.

4. 해결 방법
부동소수점 연산에서 오차를 최소화하는 방법으로는 다음과 같은 방법이 있습니다.

첫째, 부동소수점 값의 정확한 비교는 불가능하므로, 비교 대상의 차이를 특정값보다 작은지 확인하는 방식으로 비교해야 합니다.

둘째, 부동소수점 값을 최대한 정확하게 표현하는 방법으로는, 더 큰 비트 수를 사용하는 것이 있습니다. double 형을 사용하면 float 형보다 더 큰 비트 수를 사용할 수 있으므로, 정밀도가 높아질 수 있습니다.

셋째,부동소수점 값을 처리할 때 발생하는 오차를 줄이는 또 다른 방법은, 실수 연산을 가능한 한 단순하게 처리하는 것입니다. 예를 들어, 연산을 할 때 괄호를 잘 사용하거나, 연산 순서를 조정함으로써, 중간에 발생하는 근사값의 오차를 최소화할 수 있습니다.

마지막으로, 부동소수점 값을 출력할 때에도 오차를 최소화하는 방법이 있습니다. printf 함수에서 %.nf와 같은 형식으로 출력을 할 수 있는데, 여기서 n은 출력할 소수점 이하 자릿수를 의미합니다. 따라서 소수점 이하 자릿수를 적절히 조정함으로써 출력값의 오차를 최소화할 수 있습니다.

결론적으로, 부동소수점 연산에서 발생하는 오차는 컴퓨터가 실수를 근사적으로 표현하는 방식 때문에 발생합니다. 이를 최소화하기 위해서는 연산을 가능한 한 단순하게 처리하고, 출력값을 적절히 조정하는 것이 필요합니다. 또한, 부동소수점 값의 정확한 비교는 불가능하므로, 비교 대상의 차이를 특정값보다 작은지 확인하는 방식으로 비교해야 합니다.

댓글