자바스크립트를 사용하다보면 소수점을 처리해야될 일이 있지만 우리가 생각한 것과 다르게 동작하는 경험이 있을 것이다.
자바스크립트에서 발생하는 부동소수점 문제를 해결하는 방법과 이와 연관된 개념들을 알아보자.
IEEE 754는 부동 소수점 숫자를 표현하는 데 사용되는 표준이며, 이는 대부분의 컴퓨터 시스템에서 사용된다.
이 표준은 부동 소수점 숫자를 표현하는 방법과 연산을 수행하는 방법을 정의한다.
이러한 표준은 정확도와 성능 사이의 트레이드 오프를 가지고 있으며, 때로는 부동 소수점 연산에서 정확한 결과를 얻기 어려운 문제가 발생할 수 있다.
예를들어,
console.log(0.1 + 0.2); // 0.30000000000000004
위의 코드에서는 0.1과 0.2를 더하고 있지만, 예상했던 값인 0.3이 아닌 0.30000000000000004가 출력된다.
이는 IEEE 754 부동 소수점 표준의 한계로 인해 발생하는 문제이다.
이러한 문제를 피하기 위해서는 부동 소수점 연산을 정수로 변환하여 처리하거나, 부동 소수점 연산의 결과를 적절히 반올림하는 등의 방법을 사용할 수 있다.
// 부동 소수점 연산을 정수 연산으로 대체하는 함수
function add(a, b) {
// 정수로 변환하여 연산 후 다시 부동 소수점으로 변환
return (a * 100 + b * 100) / 100;
}
// 부동 소수점 연산을 사용한 예제
console.log(0.1 + 0.2); // 0.30000000000000004
// 정수 연산으로 대체한 예제
console.log(add(0.1, 0.2)); // 0.3
Number.prototype.toFixed() 메서드와 Math 객체의 메서드들을 사용하여 부동 소수점 문제를 해결하는 방법을 비교해보겠습니다.
toFixed() 메서드는 부동 소수점 숫자를 고정 소수점 표기법으로 변환한다.
이 메서드는 반올림하여 주어진 소수 자릿수까지 표시합니다.
예를 들어, toFixed(2)
를 사용하면 소수점 이하 두 자리까지 표시하고 반올림한다.
하지만 toFixed()
메서드는 숫자를 문자열로 반환하기 때문에 정확한 숫자 처리가 필요한 경우 형변환이 불가피하다.
let result = (0.1 + 0.2).toFixed(2);
console.log(result); // "0.30"
Math 객체의 메서드들을 사용하여 부동 소수점 문제를 해결할 수 있다.
주로 Math.round()
, Math.floor()
, Math.ceil()
등을 사용하여 소수점 이하를 반올림하거나 내림, 올림할 수 있다.
이러한 메서드들은 숫자를 변환하는 것이 아니라 결과를 반환하기 때문에 정확한 숫자 처리가 가능하다.
let result = Math.round((0.1 + 0.2) * 100) / 100;
console.log(result); // 0.3
console.log(Math.floor(5.95)); // 5
console.log(Math.floor(5.05)); // 5
console.log(Math.floor(5)); // 5
console.log(Math.floor(-5.05)); // -6
Math.ceil(0.95); // 1
Math.ceil(4); // 4
Math.ceil(7.004); // 8
Math.ceil(-0.95); // -0
Math.ceil(-4); // -4
Math.ceil(-7.004); // -7
부동 소수점 수를 안전하게 비교하는 사용자 정의 함수를 만들어보자.
부동 소수점 수를 비교할 때는 소수점 이하의 작은 오차를 고려해야 하고 보통 이 오차를 고려하여 두 부동 소수점 수의 차이가 아주 작은지를 확인하여 비교한다.
function compareFloats(float1, float2, epsilon = Number.EPSILON) {
return Math.abs(float1 - float2) < epsilon;
}
// 사용 예시
console.log(compareFloats(0.1 + 0.2, 0.3)); // true
console.log(compareFloats(0.1 + 0.2, 0.31)); // false
이 함수는 두 부동 소수점 수의 차이가 epsilon보다 작은지를 확인하여 비교한다.
epsilon은 기본적으로 JavaScript에서 제공하는 Number.EPSILON을 사용하며, 이는 JavaScript에서 표현 가능한 가장 작은 부동 소수점 수의 차이를 나타낸다.
사용자가 원하는 경우에는 epsilon 값을 직접 지정할 수도 있다.