HOWTO · JavaScript
JavaScript의 정수 나누기
JavaScript에서 Math.trunc 또는 Math.floor를 선택해 음수 값에서도 몫과 나머지를 올바르게 계산합니다.
이 페이지의 내용
JavaScript에는 // 정수 나눗셈 연산자가 없습니다. 일반 Number 값에서 몫의 소수 부분을 0 방향으로 버리려면 Math.trunc(dividend / divisor)를, 나머지에는 %를 사용합니다. 아래 방향 반올림이 필요한 규칙일 때만 Math.floor()를 선택합니다. 음수에서는 결과가 다르므로 축약형보다 규칙을 먼저 정하는 편이 중요합니다.
바로 답하기: 절단 또는 바닥 나눗셈 선택
정수 나눗셈은 두 규칙을 뜻할 수 있습니다. 절단 몫은 소수 자리를 없애므로 Math.trunc(-13 / 5)는 -2입니다. 바닥 몫은 음의 무한대 방향으로 반올림하므로 Math.floor(-13 / 5)는 -3입니다. 양수 입력에서는 둘 다 2가 되어, 운영 환경에서 음수가 나타날 때까지 차이가 숨을 수 있습니다.
부호 있는 값을 몫과 부호 있는 나머지로 나누는 작업에는 절단을 사용합니다. 몫이 항상 아래로 반올림되어야 하는 0 기반 버킷이나 순환 인덱싱에는 바닥 나눗셈을 사용합니다. JavaScript의 %는 항상 음수가 아닌 수학적 모듈로가 아니라 나머지를 반환하며 부호는 피제수에 따릅니다. MDN은 나머지 연산자와 수학적 모듈로를 구분합니다.
권장 Number 몫과 나머지
유한한 Number 입력에서는 Math.trunc와 %가 몫/나머지 관계를 명확히 만듭니다. 일반 정수 나눗셈에 권장되는 방법입니다. 계산 전에 제수가 0이 아닌지 확인하세요. 0이 아닌 Number를 부호 있는 0으로 나누면 부호 있는 Infinity가 되고, 0 / 0은 NaN이며 제수가 0인 Number 나머지도 NaN입니다. ECMAScript 명세가 이 경우를 정의합니다.
const dividend = 13;
const divisor = 5;
console.log(`quotient: ${Math.trunc(dividend / divisor)}`);
console.log(`remainder: ${dividend % divisor}`);
quotient: 2
remainder: 3
나머지는 결과 검증에도 도움이 됩니다. 정수 입력에서 dividend는 divisor * quotient + remainder와 같습니다. 이 관계는 검증에 유용하지만, Math.trunc로 몫을 계산하는 편이 간접적으로 유도하는 것보다 원하는 반올림 규칙을 더 분명하게 나타냅니다.
음수 피연산자와 부호 있는 나머지
음수 피연산자는 절단과 바닥 의미를 나누는 경계입니다. -13 / 5에서 절단은 -2, 바닥 나눗셈은 -3입니다. JavaScript는 0이 아닌 나머지에 피제수의 부호를 보존하므로 % 결과는 -3입니다. 어느 연산도 음수 입력에서 실패하지 않으며 서로 다른 질문에 답할 뿐입니다.
const dividend = -13;
const divisor = 5;
console.log(`truncating quotient: ${Math.trunc(dividend / divisor)}`);
console.log(`floor quotient: ${Math.floor(dividend / divisor)}`);
console.log(`remainder: ${dividend % divisor}`);
truncating quotient: -2
floor quotient: -3
remainder: -3
바닥 나눗셈 또는 모듈로가 필요한 경우
양수 제수에 음수가 아닌 모듈로가 필요하면 %가 이미 그렇게 동작한다고 가정하지 말고 나머지를 정규화합니다. 두 값이 같은 바닥 나눗셈 규칙을 쓰도록 Math.floor와 함께 사용합니다. 다음 예제는 다섯 항목 순환에는 적합하지만 모든 몫/나머지 작업에 맞지는 않습니다.
const dividend = -13;
const divisor = 5;
const quotient = Math.floor(dividend / divisor);
const modulo = ((dividend % divisor) + divisor) % divisor;
console.log(`floor quotient: ${quotient}`);
console.log(`non-negative modulo: ${modulo}`);
floor quotient: -3
non-negative modulo: 2
이 정규화는 제수가 양수라고 가정합니다. 제수가 음수일 수 있다면 원하는 규칙을 별도로 정의하고 테스트하세요.
BigInt를 이용한 큰 정확한 정수
Number는 IEEE-754 부동 소수점 값을 사용합니다. 안전한 정수 범위를 넘으면 모든 정수를 정확히 표현하지 못하므로 Number 몫이나 나머지를 신뢰하기 전에 Number.isSafeInteger로 입력을 검증하세요. 더 큰 정확한 정수에는 일관되게 BigInt를 사용합니다. BigInt 나눗셈은 0 방향으로 절단하고 나머지도 같은 부호 규칙을 따릅니다.
const dividend = 13n;
const divisor = 5n;
console.log(`quotient: ${dividend / divisor}`);
console.log(`remainder: ${dividend % divisor}`);
try {
13n / 0n;
} catch (error) {
console.log(`zero divisor: ${error.name}`);
}
try {
13n / 5;
} catch (error) {
console.log(`mixed types: ${error.name}`);
}
quotient: 2
remainder: 3
zero divisor: RangeError
mixed types: TypeError
Number와 BigInt 피연산자를 섞지 말고 연산 전에 의도적으로 변환하세요. BigInt의 0 제수는 RangeError를 던지며 Number의 0 제수와 다릅니다. 따라서 두 경우 모두 입력 검증이 유용합니다. MDN은 BigInt 나눗셈, 혼합 형식 오류, 0 제수 동작을 설명합니다.
비트 강제 변환이나 parseInt를 쓰지 않는 이유
~~value 또는 value | 0를 짧은 절단 관용구로 볼 수 있습니다. 비트 연산자는 부호 있는 32비트 정수로 강제 변환하여 범위 밖 값을 바꾸므로 일반 정수 나눗셈에는 피하세요. parseInt는 문자열 분석용이지 숫자 반올림 API가 아닙니다. MDN은 Math.trunc와 비트 변환의 차이를 설명합니다. 아래 비교는 32비트 경계와 올바른 문자열 분석을 보여 줍니다.
const value = 2 ** 32 + 1;
console.log(`Math.trunc: ${Math.trunc(value)}`);
console.log(`~~value: ${~~value}`);
console.log(`value | 0: ${value | 0}`);
console.log(`parseInt("13.8", 10): ${parseInt("13.8", 10)}`);
Math.trunc: 4294967297
~~value: 1
value | 0: 1
parseInt("13.8", 10): 13
숫자 Number 값에는 Math.trunc를 쓰고, 입력이 분석할 텍스트일 때만 parseInt(text, 10)를 사용하세요. 어느 축약형도 부동 소수점 정밀도를 고치지 못하며, 큰 정수의 정확한 산술에는 BigInt를 사용합니다.
선택 요약과 제한 사항
일반 JavaScript 정수 나눗셈에는 Math.trunc(a / b)와 a % b를 사용합니다. 바닥 의미가 필요할 때만 정규화한 모듈로와 Math.floor(a / b)를 사용합니다. 정확한 큰 정수에는 BigInt를 쓰고 0 제수를 거부하며, 한 연산에서 BigInt와 Number를 섞지 않습니다. 비트 강제 변환과 parseInt는 다른 문제를 해결하므로 범용 대안으로 피하세요.