
프로그래밍 언어를 사용하다 보면 간단한 소수 계산조차 기대와 다른 결과가 나오는 경우를 마주할 수 있다. 예를 들어,
0.1 + 0.2를 더했을 때 우리가 기대하는0.3대신0.30000000000000004같은 값이 출력된다. 이 현상은 자바스크립트만의 문제가 아니라, 대부분의 프로그래밍 언어에서 공통적으로 발생한다.
이번 글에서는 왜 이런 숫자 계산 오류가 발생하는지, 그리고 이를 해결하는 방법을 정리한다.
컴퓨터는 우리가 작성한 모든 코드를 0과 1로 이루어진 2진수 형태로 변환해 처리한다. 이 과정에서 10진수 소수를 2진수로 변환해야 하는데, 여기서 문제가 생긴다.
우리가 사용하는 10진수의 특정 소수는 2진수로 변환했을 때 무한소수가 된다. 예를 들어:
0.1을 2진수로 변환하면 0.0001100110011...처럼 끝없이 반복되는 소수가 된다.이러한 무한소수를 컴퓨터는 메모리의 한계로 인해 특정 자리까지만 저장해야 하며, 이 과정에서 반올림이 발생한다. 이렇게 반올림된 값이 연산에 사용되면서 작은 오차가 누적되고, 우리가 기대하지 않은 결과가 출력된다.
자바스크립트에서 숫자 계산 오류를 완벽히 방지할 방법은 없지만, 상황에 따라 오류를 줄이거나 원하는 결과에 가까워지도록 처리할 수 있는 대표적인 방법 두 가지를 소개한다.
toFixed 메서드 활용toFixed 메서드는 숫자를 특정 소수점 자리로 반올림하여 문자열로 반환한다.
이를 통해 소수 계산의 불필요한 오차를 줄일 수 있다.
const result = (0.1 + 0.2).toFixed(2); // 소수점 둘째 자리까지 반올림
console.log(result); // 출력: "0.30"
toFixed의 반환 값은 문자열이다. 숫자로 사용하려면 형변환이 필요하다.const numericResult = Number(result); // 숫자형으로 변환
console.log(numericResult); // 출력: 0.3
// 더 간단한 방법
const simplifiedResult = +result; // 숫자형으로 변환
console.log(simplifiedResult); // 출력: 0.3
Math.round 메서드 활용Math.round를 사용해 원하는 자리까지 반올림할 수도 있다.
이를 위해 연산 전에 10의 거듭 제곱을 곱해 정수로 만든 후 계산하고 다시 나누는 방식을 사용한다.
const precision = 2; // 소수점 자리수
const value = 0.1 + 0.2;
// 10의 거듭 제곱(100)을 곱하고 반올림 후 다시 나눔
const result = Math.round(value * Math.pow(10, precision)) / Math.pow(10, precision);
console.log(result); // 출력: 0.3
value * 100으로 소수점 두 자리까지 정수로 변환한다.Math.round를 사용해 반올림한다.100으로 나누어 원래의 자리수로 복원한다.위에서 설명한 방법들은 숫자 계산의 오차를 줄이는 방법일 뿐, 완벽히 제거할 수 있는 방법은 아니다.
예를 들어, 3분의 1(0.333...)을 정확히 표현할 수 없는 것처럼, 이진수로 표현했을 때 무한소수가 되는 경우, 컴퓨터는 항상 반올림을 수행해야 한다.
- 숫자 계산 오류 원인:
- 컴퓨터는 숫자를 2진수로 변환해 처리하며, 10진수 소수를 정확히 표현하지 못해 반올림 오차가 발생한다.
- 대표적인 해결 방법:
toFixed: 특정 소수점 자리까지 반올림 후 문자열 반환.Math.round: 원하는 자리에서 반올림 후 계산 복원.- 한계: 숫자 계산 오류를 완벽히 제거할 방법은 없으며, 상황에 따라 적절한 반올림을 활용해야 한다.
숫자 계산 오류는 프로그래밍 언어의 한계에서 기인한 문제로, 이를 완벽히 해결하기는 어렵다. 하지만 자바스크립트에서 제공하는 다양한 메서드를 활용하면 오류를 최소화할 수 있다. 상황에 따라 적절한 방법을 선택해 활용해보자.