JavaScript에서 소수점 계산을 할 때 종종 예상치 못한 결과가 발생할 수 있다. 예를 들어, price * quantity * 1.1이라는 계산식이 XXX.00000000000003과 같은 값으로 출력되는 경우가 있다. 이런 현상이 발생하는 이유는 컴퓨터의 소수점 처리 방식 때문이다.
발생 이유?
컴퓨터는 2진법(0과 1)으로 숫자를 표현한다. 하지만 10진수 소수점을 2진법으로 완벽히 변환할 수 없는 경우가 많다. 예를 들어, 1.1은 2진법으로 무한소수로 표현되기 때문에 정확한 값이 아닌 근사치로 저장되게 된다. 이로 인해 계산할 때 소수점 오차가 발생할 수 있다.
해결 방법
소수점 계산 오차를 줄이기 위해 다음과 같은 방법을 사용할 수 있다.
1. toFixed() 메서드 사용하기
toFixed() 메서드는 숫자를 문자열로 변환하고, 소수점 이하 자리수를 지정해 반올림된 값을 반환한다.
- 예시
const price = 20.0;
const quantity = 10;
const total = price * quantity * 1.1;
console.log(total.toFixed(2)); // "220.00"
- 장점:
- 간단하고 빠르게 소수점 자리수를 제한할 수 있다.
- 원하는 자리수로 반올림해 표시할 수 있다.
- 주의점:
- toFixed()는 문자열을 반환하기 때문에, 이후 계산이 필요하면 parseFloat() 또는 Number()로 변환해야 한다.
const preciseTotal = parseFloat(total.toFixed(2));
console.log(preciseTotal); // 220.00 (숫자형)
2. Math.round() 사용하기
Math.round()는 반올림을 활용하여 소수점 이하 오차를 줄일 수 있다. 소수점 두 자리까지 반올림하고 싶다면, 100을 곱하고 나누는 방식을 사용한다.
- 사용 예시:
const price = 20.0;
const quantity = 10;
const total = price * quantity * 1.1;
const roundedTotal = Math.round(total * 100) / 100;
console.log(roundedTotal); // 220.00
- 장점:
- 숫자형 데이터로 유지되기 때문에 추가적인 변환이 필요 없다.
- 반올림된 정확한 숫자 값을 반환한다.
3. 외부 라이브러리 사용하기
정밀한 계산이 자주 필요하거나 계산이 복잡한 경우, decimal.js, big.js, bignumber.js와 같은 외부 라이브러리를 사용하는 것이 좋다. 이들 라이브러리는 JavaScript의 기본 소수점 처리 문제를 해결해준다.
- 예제 코드 (decimal.js):
const Decimal = require('decimal.js');
const price = new Decimal(20.0);
const quantity = new Decimal(10);
const total = price.mul(quantity).mul(1.1);
console.log(total.toFixed(2)); // "220.00"
- 장점:
- 높은 정밀도로 소수점 계산을 수행할 수 있다.
- 복잡한 계산에서도 안정적인 결과를 보장한다.
- 단점:
- 추가적인 패키지 설치가 필요하다.
- 코드가 조금 더 복잡해질 수 있다.
4. 소수점 자리수 조절 함수 만들기
간단한 함수로 소수점 자리수를 맞추는 방법도 있다.
- 사용 예시:
function roundTo(value, decimals) {
const factor = Math.pow(10, decimals);
return Math.round(value * factor) / factor;
}
const price = 20.0;
const quantity = 10;
const total = price * quantity * 1.1;
console.log(roundTo(total, 2)); // 220.00
- 장점:
- 다양한 상황에 맞게 커스터마이징이 가능하다.
- 외부 라이브러리를 사용하지 않고도 소수점 계산 오차를 보정할 수 있다.
결론
JavaScript의 소수점 계산 오류는 2진법 소수 표현의 한계 때문에 발생하는데, 이 문제를 해결하기 위해 toFixed(), Math.round()를 사용하거나 외부 라이브러리를 활용할 수 있다.
상황에 맞는 방법을 적용하여 정밀한 계산을 보장하도록 하자.
'Languages' 카테고리의 다른 글
for vs forEach() vs map() (1) | 2024.01.06 |
---|