JavaScript / 내림·올림·반올림·버림, floor·ceil·round·trunc 차이

JavaScript에서 정수로 내림할 때는 Math.floor(), 올림할 때는 Math.ceil(), 가장 가까운 정수로 반올림할 때는 Math.round()를 사용합니다. 음수에서는 내림이 0 쪽으로 이동하는 동작이 아니며, 정확히 중간인 반올림은 양의 무한대 쪽 정수를 선택합니다.

내림·올림·반올림은 어느 방향으로 움직이나

floor는 입력 이하의 정수 중 가장 큰 값, ceil은 입력 이상의 정수 중 가장 작은 값을 반환합니다. round는 가장 가까운 정수를 고릅니다. 그래서 양수 1.4와 음수 -1.4에서 방향을 함께 비교해야 합니다.

입력 floor ceil round trunc
1.4 1 2 1 1
1.5 1 2 2 1
-1.4 -2 -1 -1 -1
-1.5 -2 -1 -1 -1
-1.6 -2 -1 -2 -1

Math.round(-1.5)는 -2가 아니라 -1입니다. -1과 -2까지의 거리가 정확히 같으면 더 큰 정수인 -1을 선택하기 때문입니다. MDN의 Math.floor() 문서, Math.ceil() 문서, Math.round() 문서의 정의를 대조하세요.

소수 부분을 버리는 trunc()와의 차이

Math.trunc()는 소수 부분을 제거하고 0 방향으로 이동합니다. 양수에서는 floor()와 같지만 음수에서는 다릅니다. “버림”이 음수에도 쓰일 요구라면 0 방향인지 음의 무한대 방향인지 먼저 정해야 합니다.

console.log(Math.floor(-1.9)); // -2
console.log(Math.trunc(-1.9)); // -1
console.log(Math.round(-1.5)); // -1
console.log(Object.is(Math.round(-0.5), -0)); // true

-0은 화면에서 0처럼 보이지만 JavaScript 숫자로는 부호가 구별됩니다. 그 차이가 중요할 때는 Object.is(value, -0)을 사용합니다. MDN의 Math.trunc() 문서가 소수 부분 제거의 의미를 설명합니다.

원하는 자릿수에서 처리할 때

소수 첫째 자리까지 남기려면 10을 곱해 정수로 처리한 다음 10으로 나눕니다. 소수 둘째 자리까지라면 100을 사용합니다. 정수의 천 단위에서 반올림하려면 1000으로 나눈 뒤 반올림하고 다시 1000을 곱합니다.

console.log(Math.round(1.25 * 10) / 10); // 1.3
console.log(Math.floor(1.256 * 100) / 100); // 1.25
console.log(Math.ceil(1.251 * 100) / 100); // 1.26
console.log(Math.round(1234567 / 1000) * 1000); // 1235000

이 계산은 이진 부동소수점 근사값을 사용합니다. 예를 들어 Math.round(1.005 * 100) / 100은 기대한 1.01 대신 1이 될 수 있습니다. Number.EPSILON을 더하는 간단한 방식이 모든 크기와 부호에서 정확한 십진 반올림을 보장하지는 않습니다.

toFixed(2)는 두 자리 소수 표기의 문자열을 반환합니다. (1.2).toFixed(2)는 "1.20"입니다. 표시 형식과 계산값을 혼동하지 마세요. 정확한 금액 계산이 필요하면 정수 단위와 범위, 요구하는 반올림 규칙을 별도로 설계해야 합니다. MDN의 toFixed() 문서를 참고하세요.

전체 예제: 양수와 음수 비교하기

아래 코드를 rounding-methods.html로 저장해 브라우저에서 엽니다. 숫자를 입력해 버튼을 누르면 네 메서드의 결과를 같은 조건에서 비교합니다. 빈 문자열과 유한하지 않은 값은 계산하지 않으며, 결과가 음의 0이면 -0으로 표시합니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>내림 올림 반올림 비교</title>
</head>
<body>
<label for="number">비교할 수</label>
<input id="number" type="number" step="any" value="-1.5">
<button id="compare" type="button">결과 비교</button>
<pre id="output" aria-live="polite"></pre>
<script>
const input = document.querySelector('#number');
const output = document.querySelector('#output');

function describe(value) {
  return Object.is(value, -0) ? '-0' : String(value);
}

function compare() {
  const text = input.value.trim();
  const value = Number(text);
  if (!text || !Number.isFinite(value)) {
    output.textContent = '유한한 숫자를 입력하세요.';
    return;
  }
  output.textContent = [
    `입력: ${text}`,
    `floor: ${describe(Math.floor(value))}`,
    `ceil: ${describe(Math.ceil(value))}`,
    `round: ${describe(Math.round(value))}`,
    `trunc: ${describe(Math.trunc(value))}`
  ].join('\n');
}

document.querySelector('#compare').addEventListener('click', compare);
compare();
</script>
</body>
</html>

기본값 -1.5의 결과는 floor=-2, ceil=-1, round=-1, trunc=-1입니다. -0.5를 입력하면 round=-0을 확인할 수 있습니다. 1.5를 입력하면 각각 1, 2, 2, 1로 바뀝니다. 이 예제의 숫자는 결과를 비교하는 용도이며, 소수 자릿수를 보증하는 금액 계산으로 사용하지 마세요.