티스토리 뷰

320x100

2021년 3월 26일 Velog에 작성한 글을 옮겨온 글입니다.

구름 - 사은품 교환하기

 

BigInt로 JavaScript에서 아주 큰 수 다루기

풀이

N개의 시즌 한정 음료 쿠폰과 M개의 일반 음료 쿠폰으로 아래 조건을 만족할 때 1개의 상품으로 교환해줍니다.

  • 하나의 상품으로 교환하기 위해서는 12장의 쿠폰이 필요하다. => 최대 (N + M) / 12개 교환 가능
  • 이 쿠폰들 중 최소 5개는 시즌 한정 음료 쿠폰이어야 한다. => 최대 N / 5개 교환 가능

로직 자체는 위의 두 조건을 모두 충족하는 값(두 값 중 최소값)을 도출하면 되는 문제입니다. 숫자가 크지 않은 경우에는 간단하게 Math.min(Math.floor(N / 5), Math.floor((N + M) / 12));와 같이 표현할 수 있습니다.

단, 이 문제에서 포인트는 입력 형식의 "N과 M은 모두 64비트 부호형 정수형 범위 내에 존재하는 0 이상의 정수다." 조건입니다.

JavaScript에서 자료형 Number는 double-precision 64-bit floating point format (IEEE 754), 64-bit 부동소숫점으로 표현됩니다. 즉, 정수 형태로 표현 가능한 범위는 -(2^53 - 1) ~ (2^53 - 1)입니다. 문제에서 64-bit 부호형 정수를 입력하고 있기 때문에 이 큰 수를 다루기 위해서는 별도의 조치가 필요합니다.

c/c++에서는 자료형을 long long형으로, java에서는 long형으로 정의하여 해결할 수 있고, JavaScript에서는 BigInt를 사용하여 해결할 수 있었습니다.

BigInt는 ES2020에서 추가된 원시타입으로 2^53 - 1(Number.MAX_SAFE_INTEGER)보다 큰 정수를 다룰 수 있습니다.

문제 풀이 시 유의할 점

  1. 연산은 BigInt끼리만 가능하다. => const K1 = N / 5n;(O) const K1 = N / 5;(X)
  2. Math 객체의 메서드 사용이 불가능하다. => K1 < K2 ? K1 : K2(O) Math.min(K1, K2)(X)
  3. BigInt 값이 Number 값으로 강제 형변환되면 정밀도가 손실될 수 있다. => String(answer)(O) Number(answer)(X)

기타 유의 사항

  1. Big"Int" 이름처럼 정수형을 위한 자료형으로 나누기 연산 시 소수점 이하는 버린 결과가 나온다.(5n / 2n=>2n)
  2.  IE에서는 지원되지 않는다.
const solution = ([N, M]) => {
	const K1 = N / 5n;
	const K2 = (N + M) / 12n;
  	const answer = K1 < K2 ? K1 : K2;
	console.log(String(answer));
};

const readline = require("readline");
const rl = readline.createInterface({
	input: process.stdin,
	output: process.stdout
});

let T = null;

rl.on("line", function(line) {
	if (T === null) {
		T = +line;
	} else {
		solution(line.split(' ').map(cur => BigInt(cur)));
		T--;
	}
	if (!T) {
		rl.close();
	}
}).on("close", function() {
	process.exit();
});

참고자료

320x100
댓글