백준 홀수일까 짝수일까(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);
코드 설명
- BigInt로 변환: 입력값을 BigInt로 변환해 큰 정수를 다룰 수 있도록 한다.
- n 접미사 사용: BigInt 연산에서는 2n, 0n처럼 숫자 뒤에 n을 붙여야 한다.
- % 연산: BigInt끼리만 연산 가능하므로, % 연산도 2n과 같은 BigInt 값을 사용한다.
결론
이 문제를 통해 알게 된 점:
- JavaScript의 Number 타입은 정수 범위에 한계가 있다. 2^53−1을 초과하는 정수는 안전하지 않으며, 정밀도가 손실될 수 있다.
- 큰 정수를 다룰 때는 BigInt를 사용하자. BigInt는 정밀도 손실 없이 큰 정수를 처리할 수 있다.
참고
'JavaScript' 카테고리의 다른 글
for문 내에 변수를 선언해도 괜찮을까? (1) | 2024.11.24 |
---|---|
데이터 타입은 왜 필요한가? 동적 타입 언어의 특징도 알아보자 (0) | 2024.08.02 |
JavaScript 원시 타입 종류 7가지 (0) | 2024.08.02 |
변수는 왜 필요한가?, 어떻게 선언되고 할당되는지도 알아보자 (feat. 메모리) (0) | 2024.07.31 |
스코프 체인 - 함수에서 어떤 값에 접근이 가능/불가능한가 따져보기 (0) | 2023.02.03 |