컴퓨터에서 실수를 표현하는 방법은 정수에 비해 훨씬 복잡하다.
실수는 정수와 달리 소수점 이하의 값을 다루어야 하기 때문에, 이를 2진수(0, 1)로만 표현해야 하는 컴퓨터에서는 다양한 방법들이 연구되어 왔다. 특히 실수 연산에서 발생하는 오차 문제는 컴퓨터 시스템에서 빈번하게 발생하며, 이를 줄이기 위해 고정 소수점과 부동 소수점 방식이 도입되었다.
이번 글에서는 두 가지 실수 표현 방식을 살펴보고, 각각의 장단점과 실수 연산의 한계에 대해 알아보자.
고정 소수점 방식은 실수를 표현할 때, 정수부와 소수부를 나타내는 비트 수를 미리 고정해두고, 이를 기반으로 실수를 표현하는 방법이다. 이 방식은 단순하지만, 정밀도와 표현 가능한 범위에 한계가 있다.

고정 소수점에서 각 비트의 역할은 다음과 같다:
0, 음수는 1로 표시된다.정수부와 소수부의 경계는 소수점의 위치에 따라 고정되며, 이진수로 변환된 값을 해당 비트에 그대로 넣으면 된다. 남는 자리는 0으로 채워 정수를 표현한다.
10진수 는 2진수로 변환하면 이 된다. 이를 고정 소수점 방식으로 표현하면 정수부에는 , 소수부에는 을 각각 저장한다.

부동 소수점은 소수점이 고정되지 않고 “떠다니는” 방식으로, 보다 넓은 범위의 실수를 표현할 수 있는 방식이다. IEEE 754 표준은 가장 널리 사용되는 부동 소수점 표현 방식이다.

부동 소수점에서의 각 비트는 다음과 같은 의미를 가진다:
0, 음수는 1로 표시된다.💡 Bias란?
부동 소수점 표현 방식에서 지수를 저장할 때 사용하는 보정 값이다. 이를 통해 지수가 음수인 경우에도 양수로 변환해 저장할 수 있도록 도와주는 개념이다. Bias는 특히 IEEE 754 부동 소수점 표준에서 사용된다.
예를 들어 IEEE 754 표준에서는 32비트 부동 소수점에서 Bias 값은 127로 사용한다.
를 2진수로 변환한 후, 이를 정규화하면 형태가 된다. 지수에 127의 bias를 더해 지수부에 저장하고, 가수부에는 소수부를 저장한다.
실수 연산에서 발생하는 오차 문제는 부동 소수점 방식에서 흔하게 나타난다. 예시 코드로 살펴보자:
const f = () => {
const a = 0.1;
const b = 0.2;
if (a + b === 0.3) {
console.log('Same');
} else {
console.log('Different');
}
};
위 코드의 출력 결과는 ‘Different’이다. 이는 과 가 이진수로 정확하게 표현할 수 없는 무한 소수이기 때문에 발생한다. 컴퓨터에 저장될 때는 에 가장 가까운 값으로 저장되며, 그 결과 두 수의 합이 처럼 약간의 오차를 포 함하게 된다.
정확한 실수 연산을 위해 정수로 변환한 후 계산하는 방법을 사용할 수 있다. 실수에 10을 곱해 정수로 만든 뒤 연산을 수행하는 방식이다.
const f = () => {
const a = 0.1;
const b = 0.2;
const intA = a * 10;
const intB = b * 10;
const intResult = 0.3 * 10;
if (intA + intB === intResult) {
console.log('Same');
} else {
console.log('Different');
}
};
은 과 같은 값이지만, 이 값을 정수로 변환(내부적으로는 소수점을 없애고 정수로 취급)하는 과정에서 오차가 보정되어 정확한 로 간주될 수 있다.
컴퓨터가 0과 1만으로 데이터를 표현해야 하다 보니, 인간이 실수를 단순하게 표현하는 것보다 훨씬 복잡한 연구가 필요했을 것 같다. 특히, 우리가 무시할 수 있는 작은 오차라도, 우주선처럼 극도로 정밀한 연산이 필요한 상황에서는 그 오차가 매우 중요한 문제가 되었을 것이다.
실제로 내가 짜는 코드에서도 많은 연산이 이루어졌을 텐데, 지금까지 이런 실수 표현으로 인한 오류를 경험하지 않았다는 게 신기하다. 만약 그런 오류가 발생했더라면, 왜 틀렸는지 고민하며 시간을 보냈을 것이다. 이제 이런 개념을 알게 되었으니, 향후 비슷한 문제가 발생했을 때 떠올릴 수 있는 문제 원인을 하나 알게 되어 유익했다.
Reference
👍