JavaScript

JavaScript에서 Number의 큰 수 처리 한계, BigInt로 해결

sangchu 2024. 11. 28. 21:10

백준 홀수일까 짝수일까(5988번) 라는 문제를 푸는데… 계속 ‘틀렸습니다’가 뜨는것이다. 이는 간단히 홀짝만 판단하면 되는 문제였다.

분명히 올바르게 짠 코드 같은데, 대체 뭐가 문제였을까?

 

먼저 문제를 간단히 설명하자면 다음과 같다.

 

문제 설명

요약

N개의 정수가 주어질 때, 각각 홀수인지 짝수인지를 출력하는 프로그램을 작성하는 것이다.

 

입력

  • 첫 번째 줄: 숫자의 개수 N(1 <= N <= 100)
  • 두 번째 줄부터 N+1번째 줄: 정수 K (1 <= K <= 10^60)
2
1024
593

출력

  • N개의 줄에 걸쳐 한 줄씩 정수 K가 홀수라면 'odd'를, 짝수라면 'even'을 출력.
even
odd

 

내가 처음에 작성한 코드

아래는 처음 작성한 코드다. 문제 조건에 맞춰 홀짝 여부를 판단했다.

let input = require("fs").readFileSync("/dev/stdin").toString().trim().split("\n").map(Number);
input.shift()

let answer = "";

for (let number of input) {
  if (number % 2 === 0) answer += "even\n";
  else answer += "odd\n";
}

console.log(answer);

근데 계속 ‘틀렸습니다’가 뜨는것이다..

‘아니, 단순히 홀짝 판단을 하는건데 도대체 뭐가 틀린건데?!!!’

 

결론은, 큰 수를 고려하지 못한것이다. 문제 조건을 보면 정수 K의 범위는 (1 <= K <= 10^60) 이다.

이 범위는 JavaScript의 Number 타입으로 처리하기엔 너무 컸다.

 

JavaScript의 Number 타입 한계

JavaScript의 Number 타입은 IEEE 754 배정밀도 부동소수점 형식을 사용한다. 이로 인해 다음과 같은 한계가 있다:

 

안전한 정수 범위

  • JavaScript에서 안전하게 정수를 표현할 수 있는 범위는 -2^53 + 1에서 2^53 - 1까지다.
    이는 Number.MAX_SAFE_INTEGER로 정의되며, 값은 다음과 같다:

  • 안전 정수 범위를 벗어나면 정밀도 손실이 발생해 정확한 값을 표현할 수 없다.

콘솔에서 직접 확인해본 결과

 

문제에서의 한계

  • 문제 조건의 K는 최대 10^60까지로, 이는 2^53−1을 훨씬 초과한다.
  • 따라서 Number 타입으로 처리할 경우, 값이 손실되거나 부정확한 결과가 나올 수 있다.

 

해결: BigInt 활용

BigInt란?

BigInt는 Number 원시 값이 안정적으로 나타낼 수 있는 최대치인 2^53 - 1보다 큰 정수를 표현할 수 있는 내장 객체다.

이를 통해 10^60 같은 큰 정수도 정확히 처리할 수 있다.

 

수정된 코드

아래는 BigInt를 사용해 문제를 해결한 코드다:

let input = require("fs").readFileSync("/dev/stdin").toString().trim().split("\n");
input.shift()

let answer = "";

for (let number of input) {
  let bigNumber = BigInt(number); // BigInt로 변환
  
  if (bigNumber % 2n === 0n) answer += "even\n";
  else answer += "odd\n";
}

console.log(answer);

코드 설명

  1. BigInt로 변환: 입력값을 BigInt로 변환해 큰 정수를 다룰 수 있도록 한다.
  2. n 접미사 사용: BigInt 연산에서는 2n, 0n처럼 숫자 뒤에 n을 붙여야 한다.
  3. % 연산: BigInt끼리만 연산 가능하므로, % 연산도 2n과 같은 BigInt 값을 사용한다.

 

결론

이 문제를 통해 알게 된 점:

  1. JavaScript의 Number 타입은 정수 범위에 한계가 있다. 2^53−1을 초과하는 정수는 안전하지 않으며, 정밀도가 손실될 수 있다.
  2. 큰 정수를 다룰 때는 BigInt를 사용하자. BigInt는 정밀도 손실 없이 큰 정수를 처리할 수 있다.

 

참고

MDN | BigInt

MDN | Number