본문 바로가기
Programming/4. JavaScript & React

011_'절대값이 2^53보다 크거나 같은 숫자 리터럴은 너무 커서 정수로 정확하게 표시할 수 없습니다.'

by @sangseophwang 2022. 3. 15.

console.log("333333333333333333" - "3");

// "333333333333333300"

// ??????????????????????????

???

- 최근 블로그 스터디를 하면서 한 분이 이런 질문을 하셨다.
- '왜 계산이 이렇게 되는 걸까요?'
- 그래서 직접 이리저리 텍스트를 바꿔가며 테스트를 해봤는데 여전히 정확한 계산이 안되는 것이었다.
- 그러다 숫자로 값을 변경하면서 다음과 같은 사실을 알게 됐다.

 

Number라고 생각했지만 Number가 아니다?

- 위 에러 메세지에서 '절대값이 2^53보다 크거나 같은 숫자 리터럴'에 주목할 필요가 있다.
- JavaScript의 Number는 부동 소수점으로 표시된다. 이는 정밀도가 제한적이라는 것을 의미한다.
- 그래서 그 제한적인 정밀도의 마지선은 아래 코드를 보며 확인해보자!
const max = Number.MAX_SAFE_INTEGER;
const min = Number.MIN_SAFE_INTEGER;

console.log(max);
console.log(min);

// 9007199254740991
// -9007199254740991
- Number.MAX(MIN)_SAFE_INTEGER 상수는 안전하게 증가할 수 있는 최대(최소) 정수를 제공한다.
- 그래서 max를 기준으로 이 길어보이는 숫자를 풀어보면 (2^53) - 1 이 나온다.
- 최대 범위는 2^53이며, 이를 벗어나게 되면 계산의 정밀도를 잃게 되며, 이러한 이유 때문에 안전 범위 내 숫자 정수 값만 신뢰할 수 있다.

 

그래서 나온 BigInt

- BigInt는 정수의 최대, 최소 범위를 초과한 정수를 안전하게 저장하고 조작할 수 있는 JavaScript의 새로운 숫자 데이터 형이다.
- 사용 방법은 간단하다. 정수 뒤에 n을 붙이거나 함수 BigInt()를 호출해 사용하면 된다.
- BigInt의 타입은 'number'가 아닌 'bigint'이다.
- 따라서 Number 타입과 혼합해 연산에 사용할 수 없다. 즉, 모두 BigInt 형으로 바꿔야 연산이 가능하다.
- 또한 BigInt는 내장 Math 객체의 메서드와 함께 사용할 수 없다.
- BigInt를 Number로 바꾸면 정확성을 잃을 수 있다!
// BigInt 타입
typeof 100n === 'bigint'   
// true


// 타입 비교
0n === 0      
// false


// 일반 비교는 가능

1n < 2
// true

2n > 1
// true


// if, 논리 연산자(||, &&, !), Boolean같은 상황에서는 Number처럼 행동한다.

if (0n) {
  console.log('if에서 안녕!');
} else {
  console.log('else에서 안녕!');
}
// "else에서 안녕!"
- 권장사항으로 BigInt를 Number로 변환하는 과정에서 정확도를 유실할 수 있으므로,  2^53보다 큰 값을 예상할 수 있는 경우 BigInt만 사용하는 것이 좋다.
- BigInt는 인터넷 익스플로러에서는 사용할 수 없다!!
- 소수점 결과를 포함하는 연산을 BigInt와 사용하면 소수점 이하는 사라진다!
const rounded = 5n / 2n;

console.log(rounded);
// 2.5n이 아니라 2n

 

 

출처

https://frontdev.tistory.com/entry/JS-8%EB%B2%88%EC%A7%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-BigInt
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/BigInt
반응형

댓글