자바스크립트에서 소수점을 관리하는 다양한 방법들이 있다. 이 포스트에서는 소수점 이하를 내리거나 올리거나 반올림하고 자르는 일반적인 방법들을 소개하고, 각각의 특성과 사용 상황을 설명한다.
Math.floor()
-Math.ceil(-x)
로도 얻을 수 있다.💡 이는
Math.ceil(-x)
가-x
를 올림하여 가장 가까운 큰 정수로 만들고, 그 결과에 다시 음수를 붙이면Math.floor(x)
와 동일한 값을 반환하기 때문이다. 보통은 이렇게 사용하지 않으니,Math.floor()
와Math.ceil()
의 동작 방식으로 참고만 하자.
소수점 이하를 무시하고 정수 부분만 필요할 때, 음수와 양수의 일관된 내림 처리가 필요할 때 주로 사용된다. 매우 빠르게 작동하며, 금액 계산 등에서 유용하다.
음수의 경우 기대와 다른 결과가 나올 수 있다. 예를 들어, -4.1
은 -5
가 된다. 이는 음수 방향으로 더 작은 값을 반환하기 때문이다.
console.log(Math.floor(4.9)); // 4
console.log(Math.floor(-4.9)); // -5
Math.trunc()
Math.trunc(4.9)
는 4
를 반환하고, Math.trunc(-4.9)
는 -4
를 반환한다.소수점 이하를 제거하고 싶을 때, 특히 음수의 절대값이 유지되어야 할 때 유용하다. 단순히 소수점 이하를 제거할 수 있다.
음수의 경우 절대값이 낮아진다. -4.9
는 -4
가 되기 때문이다.
console.log(Math.trunc(4.9)); // 4
console.log(Math.trunc(-4.9)); // -4
parseInt()
문자열을 정수로 변환하면서 소수점 이하를 제거하는 함수이다. 진법(radix)을 지정하지 않으면 10진법을 기본으로 사용하지만, 문자열이 "0x" 또는 "0X"로 시작하면 16진법으로 간주한다.
parseInt('4.9')
와 parseInt(4.9)
모두 4로 변환된다.
문자열로 표현된 숫자를 정수로 변환할 때 유용하다. 문자열을 정수로 변환하면서 소수점 이하를 제거할 수 있다.
입력이 숫자가 아니라 문자열로 간주되므로 주의가 필요하다. 예를 들어, parseInt('4.9')
도 4로 변환된다.
console.log(parseInt(4.9)); // 4
console.log(parseInt(-4.9)); // -4
Math.ceil()
-Math.floor(-x)
와 동일하다.💡
Math.ceil(3.2)
는4
를 반환하고,Math.ceil(-3.2)
는-3
을 반환한다. 반면,Math.floor(-3.2)
는-4
를 반환하고, 이를 다시 음수로 만들면-3
이 되어Math.ceil(3.2)
와 동일한 결과를 얻을 수 있다.
소수점 이하를 올리고 싶을 때, 최대치를 계산하거나 양수의 경우 결과를 올림 처리할 때 유용하다. 소수점 이하를 무조건 올릴 수 있다.
음수의 경우 절대값이 낮아지므로 주의가 필요하다. 예를 들어, -4.9
는 -4
가 된다.
console.log(Math.ceil(4.1)); // 5
console.log(Math.ceil(4.9)); // 5
console.log(Math.ceil(-4.1)); // -4
console.log(Math.ceil(-4.9)); // -4
Math.round()
소수점 이하를 반올림하는 함수이다. 0.5 이상은 올림, 0.5 미만은 내림 처리한다. 두 정수가 x
와 동일하게 가까운 경우 더 큰 정수로 반올림된다.
예를 들어, Math.round(2.5)
는 3
을 반환하고, Math.round(-2.5)
는 -2
를 반환한다. 이는 2.5
와 -2.5
가 각각 2
와 3
, -2
와 -3
사이에 있지만 더 큰 절대값으로 반올림되기 때문이다.
반올림이 필요할 때, 평균값 계산 등에서 유용하다. 0.5 이상은 올림, 0.5 미만은 내림 처리가 가능하다.
정확히 0.5인 경우 올림 처리되므로 주의가 필요하다.
console.log(Math.round(4.5)); // 5
console.log(Math.round(4.4)); // 4
console.log(Math.round(-4.5)); // -4
console.log(Math.round(-4.6)); // -5
toFixed()
숫자를 문자열로 변환하여 지정된 소수점 이하 자리수까지 자르는 함수이다. 지정된 소수점 자리에서 반올림하여 결과를 반환한다.
예를 들어, 5.56789.toFixed(2)
는 "5.57"
을 반환한다. 이는 소수점 둘째 자리에서 반올림된 결과이다.
특정 소수점 이하 자리까지 숫자를 표시하고 싶을 때 유용하다. 원하는 소수점 이하 자리까지 정확하게 자를 수 있다.
결과가 문자열로 반환되므로, 다시 숫자로 변환이 필요할 수 있다.
let num = 5.56789;
console.log(num.toFixed(2)); // "5.57"
console.log(num.toFixed(0)); // "6"
console.log(num.toFixed(4)); // "5.5679"
toPrecision()
숫자를 문자열로 변환하여 지정된 유효 자릿수까지 자르는 함수이다. 지정된 유효 자릿수에서 반올림하여 결과를 반환한다.
예를 들어, 5.56789.toPrecision(2)
는 "5.6"
을 반환한다. 이는 두 자리의 유효 숫자로 반올림된 결과이다.
전체 유효 자릿수를 지정하여 숫자를 표시하고 싶을 때 유용하다. 원하는 유효 자릿수까지 숫자를 정확하게 표시할 수 있다.
결과가 문자열로 반환되므로, 다시 숫자로 변환이 필요할 수 있다.
let num = 5.56789;
console.log(num.toPrecision(2)); // "5.6"
console.log(num.toPrecision(4)); // "5.568"
console.log(num.toPrecision(6)); // "5.56789"
toFixed()
와 toPrecision()
의 차이toFixed()
는 소수점 이하 자리수를 기준으로 숫자를 반올림하여 문자열로 반환한다. 예를 들어, 5.56789.toFixed(2)
는 "5.57"
을 반환한다.
toPrecision()
은 전체 유효 자릿수를 기준으로 숫자를 반올림하여 문자열로 반환한다. 예를 들어, 5.56789.toPrecision(2)
는 "5.6"
을 반환한다.
소수점을 다루는 방법에는 위의 방법 외에도 여러 가지가 있으며, 각 방법의 성능과 사용 목적에 따라 적절한 방법을 선택해야 한다. 일반적으로 소수점을 관리할 때 자주 사용되는 Math
함수, parseInt()
의 사용 상황을 요약 정리해 보겠다.
Math 함수보다 더 빠른 방법으로는 비트 연산을 사용할 수 있다. 비트 연산은 매우 빠르게 수행되며, 특히 소수점 이하를 제거하는 경우에 유용하다. 예를 들어, Math.floor()
와 같은 결과를 ~~x
또는 x | 0
와 같이 비트 연산자를 사용하여 얻을 수 있다.
비트 연산은 숫자를 이진수로 변환한 후, 각 비트에 대해 연산을 수행하는 방법이다. 하지만 비트 연산은 32비트 정수로 변환되므로, 큰 숫자의 경우 정확도가 떨어질 수 있다. 32비트 범위를 넘어가는 큰 숫자는 부정확한 결과를 초래할 수 있다. 예를 들어, ~~2147483648.1
는 -2147483648
를 반환한다.
console.log(~~4.9); // 4
console.log(4.9 | 0); // 4
console.log(~~-4.9); // -4
console.log(-4.9 | 0); // -4
비트 연산은 Math 함수보다 빠르게 동작하지만, 그 차이는 대부분의 경우 미미하다. 실제 애플리케이션에서 이러한 성능 차이가 크게 영향을 미치는 경우는 드물다. 일반적으로 성능 차이는 매우 많은 수의 연산이 반복될 때나 실시간 성능이 중요한 게임 개발 등에서만 유의미하다.
그러나 비트 연산은 32비트 정수 범위 내에서만 정확하게 동작하므로, 큰 숫자를 다룰 때는 부정확한 결과를 초래할 수 있다. 따라서 32비트 범위를 넘어가는 숫자를 다룰 때는 Math 함수를 사용하는 것이 더 안전하다.
소수점 이하를 관리할 때는 Math 함수를 사용하는 것이 정확하고 일관된 결과를 제공하며, 코드 가독성도 높다. 비트 연산은 더 빠를 수 있지만, 32비트 정수 범위 내에서만 정확하게 동작하므로, 큰 숫자를 다룰 때는 Math 함수를 사용하는 것이 적절하다. 그리고 대부분의 경우 두 방법에 대한 성능 차이는 미미하다. 성능이 아주 중요한 특수한 경우에만 비트 연산을 사용하는 것이 좋다.