js의 Number, BigInt 타입과 정밀한 숫자 계산에 대하여
js는 Int, long, float, double 이런 타입이 존재하지 않고 상남자스럽게 "number" 타입 하나만 존재한다.
최근에, 돈이 오고가는 프로젝트를 node로 개발해볼까 싶어서 한 번 짚어보았다.
- object wrapping var, 일반 var
이건 java할 때도 살펴보았으니 설명은 생략.
object로 wrapping 된 녀석은 object 타입이며 자기 자신과 비교할 때만 true를 반환합니다. object라니깐요?
const a = new Number("123"); // create a wrapper object
const b = Number("123"); // 단순 primitive 값 반환
const c = 123; // 단순 primitive 값 반환
console.log(a === b); // false
console.log(b === c); // true
console.log(a instanceof Number); // true
console.log(b instanceof Number); // false
- Number 타입에서 한계치로 다룰 수 있는 값은 어디까지인가?
Number의 MAX_SAFE_INTEGER, MIN_SAFE_INTEGER로 안전하게 계산할 수 있는 정수값을 알 수 있습니다.
자바스크립트에서는 정수 중 최대 2^53 - 1까지 안전하게 다룰 수 있다고 알려져있습니다.
Max이상으로 값을 더하거나, Min이하로 값을 빼려고하면, 에러는나지 않지만 정상적인 값을 출력하지 않습니다.
해당 값들이 안전한 값 내부인지 확인해보기 위해서는 Number.isSafeInteger 메서드를 통해 확인해볼 수 있습니다.
현재는 Max값보다 + 1된 값을 반환하므로 false를 반환합니다.
let Max = Number.MAX_SAFE_INTEGER; // 9007199254740991
let Min = Number.MIN_SAFE_INTEGER; // -9007199254740991
console.log(Max);
console.log(Min);
console.log(Max++); // ????
console.log(Number.isSafeInteger(Max++)); // false
- BigInt
developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/BigInt
위와 같은 Number의 한계로, BigInt를 사용합니다.
BigInt의 특징
- 2^53 - 1 보다 더 큰 수를 다룰 수 있게 됨
- 그러나 Number 타입과 같이 섞어 연산할 수 없음. 다만 비교는 가능함.
- BigInt는 BigInt 끼리 비교, 연산해야 함. 당연히 일반 Number보다는 속도 측면에서 느림
- Math 내장 객체의 메서드도 사용할 수 없음
- 그러나 +, *, -, **, % 연산자는 사용 가능함.
선언 방법
let a = 9007199254740996n; // 리터럴 뒤에 n을 붙여 선언
let b = BigInt(Number.MAX_SAFE_INTEGER + 6); // 혹은 BigInt로 선언
console.log(a, b); // 9007199254740996n, 9007199254740996n
- 숫자 계산을 위한 외부 라이브러리
숫자의 정확도가 중요하면 왜 js를 쓰냐?는 반문이 먼저 나오는 게 맞다고 생각하는데, 그래도 외부 라이브러리를 이용해 정확한 숫자 계산을 할 수 있다.
accounting.js, decimal.js, bignumber.js 등 여러 라이브러리가 존재하는데, 안타깝게도 node까지는 지원해도 deno를 지원하는 툴은 없더라. big.js는 반면에 deno를 지원해서 가져와봤다.
big.js.
- deno까지 지원해서 좋음 ㅎ
- UI / 차트, 캔버스, 도면 등 성능이 중요한 경우에는 이 라이브러리를 사용하면 안된다
- definitelyTyped 지원