본문 바로가기
자바 스크립트

자바스크립트 숫자형

by y00ns00 2020. 12. 11.

모던 자바스크립트는 숫자를 나타내는 두 가지 자료형을 지원한다.

 

1. 일반적인 숫자는 '배정밀도 부동소수점 숫자'로 알려진 64비트 형식의 IEEE-754에 저장된다.

 

2. 임의이 길이를 가정 정수는 Bigint 숫자로 나타낼 수 있다. 

일반적인 숫자는 2의53승  이상이거나 -2의 53승 이하일 수 없다는 제약 때문에 BigInt라는 새로운 자료형이 만들어 졌다.

BigInt는 아주 특별한 경우에만 사용된다.

 

숫자를 입력하는 다양한 방법

일반적인 숫자는 253이상이거나 -253이하일 수 없다는 제약 때문에 BigInt라는 새로운 자료형이 만들어졌다.

 

10억을 입력한다고 가정했을때 가장 분명한 방법은 10억 을 써주는 것 이다.

let billion = 1000000000;

하지만 0을 많이 사용해 숫자를 표현하다 보면 잘못 입력하기 쉽기때문에 실제로는 이런 방법을 잘 사용하지 않는다.

때문에 10억을 나타낼 땐 '1bn'을 사용하고 73억을 나타낼 땐 '7.3bn'을 사용한다. 

 

자바 스크립트에서도 숫자 옆에 'e'를 붙이고 0의 개수를 그 옆에 붙여주면 숫자를 줄일 수 있다.

let billion = 1e9;  // 10억, 1과 9개의 0

alert( 7.3e9 );  // 73억 (7,300,000,000)

즉 'e'는 왼쪽에 수에 e오른쪽에 있는 수만큼 10의 거듭제곱을 곱하는 효과가 있다.

 

 

작은 숫자를 표현할 때도 큰 숫자를 표현할 때처럼'e'를 사용할 수  있다.

0을 명시적으로 쓰고 싶지 않다면 다음과 같이 숫자를 표현할 수 있다.

let ms = 1e-6; // 1에서 왼쪽으로 6번 소수점 이동

 

'e' 우측에 음수가 있으면 이 음수의 절댓값만큼 10을 거듭제곱한 수로 나누는 것을 의미한다.

// 10을 세 번 거듭제곱한 수로 나눔
1e-3 = 1 / 1000 (=0.001)

// 10을 여섯 번 거듭제곱한 수로 나눔
1.23e-6 = 1.23 / 1000000 (=0.00000123)

 

 

16진수 2진수 8진수

16진수는 색을 나타내거나 문자를 인코딩 할 때 등 다양한 곳에서 두루 사용한다. 

16진수는 '0x'를 사용해 표현할 수 있다.

alert( 0xff ); // 255
alert( 0xFF ); // 255 (대·소문자를 가리지 않으므로 둘 다 같은 값을 나타냅니다.)

 

2진수와 8진수는 아주 드물게 쓰이긴 하짐나 접두사 0b와 0o를 사용해 간단히 나타낼 수 있다.

let a = 0b11111111; // 255의 2진수
let b = 0o377; // 255의 8진수

alert( a == b ); // true, 진법은 다르지만, a와 b는 같은 수임

자바스크립트에서 지원하는 진법은 3개이다.

이 외의 진법을 사용하려면 함수 parseInt를 사용해야 한다.

 

 

toString(base)

num.toString(base) 메서드는 base 진법으로 num을 표현한 후 이를 문자형으로 변환해 반환한다.

let num = 255;

alert( num.toString(16) );  // ff
alert( num.toString(2) );   // 11111111

base는 2에서 36까지 쓸 수 있는데 기본값은 10 이다.

 

- base=16 - 16진수 색,문자 인코딩 등을 표현할 때 사용한다. 숫자는 0부터9, 10이상의 수는 A부터 F를 사용하여 나타낸다.

- base = 2 - 비트 연산 딛버깅에 주로 쓰인다. 숫자는 0 또는 1이 될 수 있다.

- base = 36 - 사용할 수 있는 base 중 최댓값으로 0..9와 A...Z를 사용해 숫자를 표현합니다.

알파벳 전체가 숫자를 나타내는데 사용된다. 36베이스는 url을 줄이는 것과 같이 숫자로 된 긴 식별자를 짧게 줄일 때 유용하다.

alert( 123456..toString(36) ); // 2n9c

점 두 개와 메서드 호출 

123456..toString(36)에 있는 점 두 개는 오타가 아니다.

숫자를 대상으로 메서드 toString을 직접 호출하고 싶다면 숫자 다음에 점 두 개 ..를 붙여야 한다.

123456.toString(36)처럼 점을 한 개만 사용하면, 첫 번째 점 이후는 소수부로 인식되어 에러가 발생할 수 있다.

점을 하나 더 추가하면 자바스크립트는 소수부가 없다고 판단하고 함수를 호출합니다.

(123456).toString(36)도 가능하다.

 

어림수 구하기

어림수를 구하는 것(rounding)은 숫자를 다룰 때 가장 많이 사용되는 연산 중 하나이다.

 

어림수 관련 내장 함수 몇 가지

Math.floor

소수점 첫째 자리에서 내림(버림)3.1은 3, -1.1은 -2가 된다.

 

Math.ceil

소수점 첫째 자리에서 올림 3.1은4, -1.1은 -1이 된다.

 

Math.round

소수점 첫째 자리에서 반올림 3.1 은 3, 3.6은 4, -1.1은 -1이 된다.

 

Math.trunc

소수부를 무시 3.1은 3이되고 -1.1은 -1 이 된다.

 

toFixed(n) -> 소수점 n 번째 수까지의 어림수를 구한 후 이를 문자형으로 반환해주는 메서드 

 

 

부정확한 계산

숫자는 내부적으로 64비트 형식 IEEE-754우로 표현되기 때문에 숫자를 저장하려면 정확히 64비트가 필요하다

52비트는 숫자를 저장하는 데 사용되고 11비트는 소수점 위치를(정수는 0), 1 비트는 부호를 저장하는데 사용

하지만 숫자가 너무 커지만 64비트 공간이 넘쳐서 infinity로 처리된다.

alert( 1e500 ); // Infinity

 

정밀도 손실(loss of precision)

alert( 0.1 + 0.2 == 0.3 ); // false

 

0.1과 0.2의 합이 0.3과 일치하지 않는다.

alert( 0.1 + 0.2 ); // 0.30000000000000004

숫자는 0과 1로 이루어진 이진수로 변환되어 연속된 메모리 공간에 저장된다.

그런데 10 진법을 사용하면 쉽게 표현할 수 있는 0.1,0.2 같은 분수는 이진법으로 표현하면 무한 소수가 된다.

 

10진법에서 1/3을 정확히 나타낼 수 없듯이 2진법을 사용해 0.1 또는 0.2를 정확하게 저장하는 방법은 없다.

 

IEEE-754에서는 가능한 가장 가까운 숫자로 반올림하는 방법을 사용해 이런 문제를 해결한다.

그런데 반올림 규칙을 적용하면 발생하는 '작은 정밀도 손실'을 우리가 볼 수는 없지만 실제로 손실은 발생한다.

 

정밀도 손실 확인

alert( 0.1.toFixed(20) ); // 0.10000000000000000555

그리고 두 숫자를 합하면 '정밀도 손실'도 더해지낟.

0.1+0.2 가 정확히 0.3이 아닌 이유가 여기에 있다.

 

가장 신뢰할만한 해결 방법은 toFixed(n)메서드를 사용해 어림수를 만드는 것이다.

let sum = 0.1 + 0.2;
alert( sum.toFixed(2) ); // 0.30

toFixed는 항상 문자열을 반환한다는 점에 유의해야 한다. 문자열을 반환하기 때문에 소수점 다음에 오는 숫자가 항상 2개가 될 수 있다.

 

하지만 마지막에 나눗셈이 들어가끼때문에 소수가 다시 등장 할 수 있다는 단점이 있다.

alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001

 

 

 

#두 종류의 0

자바 스크립트 내부에서 숫자를 표현하는 방식 때문에 발생하는 또 다른 흥미로운 현상은 0과 -0이라는 두종류의 0이 존재한다.

자바 스크립트에서는 숫자의 부호가 단일 비트에 저장되는데 0을 포함한 모든 숫자에 부호를 설정할 수도, 설정하지 않을 수도 있기 때문이다.

대부분 연산을 0과 -0을 동일하게 취급하기 때문에 두 0의 차이는 두드러지지 않는 편이다.

 

 

isNaN과 isFinite

 

Infinity 와 -Infinity- 그 어떤 숫자보다 큰 혹은 작은 특수 숫자 값

NaN - 에러를 나타내는 값

 

두 특수 숫자는 숫자형에 속하지만 '정상적인' 숫자는 아니기 때문에 정상적인 숫자와 구분하기 위한 특별한 함수가 존재

 

- isNaN(value) - 인수를 숫자로 변환한 다름 NaN인지 테스트함 

alert( isNaN(NaN) ); // true
alert( isNaN("str") ); // true

NaN은 NaN 자기 자신을 포함하여 그 어떤 값과도 같지 않다는점에서 독특하다.

alert( NaN === NaN ); // false

 

- isFinite(value) - 인수를 숫자로 변환하고 변환한 숫자가 NaN/Infinity/-Infinity가 아닌 일반 숫자인 경우 true를 반환함

alert( isFinite("15") ); // true
alert( isFinite("str") ); // false, NaN이기 때문입니다.
alert( isFinite(Infinity) ); // false, Infinity이기 때문입니다.

 

isFinite는 문자열이 일반 숫자인지 검증하는데 사용되고는 한다.

(빈 문자열이나 공백만 있는 문자열은 isFinite를 포함한 모든 숫자 관련 내장 함수에서 0으로 취급된다)

let num = +prompt("숫자를 입력하세요.", '');

// 숫자가 아닌 값을 입력하거나 Infinity, -Infinity를 입력하면 false가 출력됩니다.
alert( isFinite(num) );

 

 

#object.is와 비교하기

Object.is는 === 처럼 같을 비교할 때 사용되는 특별한 내잗ㅇ 메서드인데 아래와 같은 두가지 에지 케이스 에서는 === 보다 좀 더 신뢰할 만한 결과를 보여준다.

 

1. NaN을 대상으로 비교할 때 - Object.is(NaN, NaN) === true

2. 0과 -0이 다르게 취급되어야 할 때:Objectis(0,-0) === false 이다.

숫자를 나타내는 비트가 모두 0이더라도 부호를 나타내는 비트는 다르므로 0과 -0은 사실 다른 값이다.

 

두 에지 케이스를 제외하고는 Object.is(a, b)와 a===b의 겨로가는 같다.

 

 

 

parseInt와 parseFloat

단항 덧셈 연산자+ 또는 Number()를 사용하여 숫자형ㅇ으로 변형할 때 적용되는 규칙은 꽤 엄격하다.

피연산자가 숫자가 아니면 형변환이 실패한다.

alert( +"100px" ); // NaN

엄격한 규칙이 적용되지 않는 유일한 예외는 문자열의 처음 또는 끝에 공백이 있어서 공백을 무시할 때

 

실무에서 CSS등 '100px', '12pt' 와 같이 숫자와 단위를 함께쓰는 경우가 흔하다 

이경우 쑷자만 추출하는 방법이 parseInt ,parseFloat이다.

 

두 함수는 불가능할 때까지 문자열에서 숫자를 읽는다. 숫자를 읽는 도중 오류가 발생하면 이미 수집된 숫자를 반환 

parseInt는 정수 parseFloat는 부동 소수점 숫자를 반환한다.

alert( parseInt('100px') ); // 100
alert( parseFloat('12.5em') ); // 12.5

alert( parseInt('12.3') ); // 12, 정수 부분만 반환됩니다.
alert( parseFloat('12.3.4') ); // 12.3, 두 번째 점에서 숫자 읽기를 멈춥니다.

 

 

parseInt(str, radix)의 두 번째 인수

parseInt()의 두 번째 매개 변수는 선택적으로 사용할 수 있습니다. radix는 원하는 진수를 지정해 줄 때 사용한다.

따라서 parseInt를 사용하면 16진수 문자열, 2진수 문자열 등을 파싱할 수 있다.

alert( parseInt('0xff', 16) ); // 255
alert( parseInt('ff', 16) ); // 255, 0x가 없어도 동작합니다.

alert( parseInt('2n9c', 36) ); // 123456

 

 

기타 수학 함수

자바스크립트에서 제공하는 내장 객체 Math에는 다양한 수학 관련 함수와 상수들이 들어있다.

 

Math.random() 

0과 1 사이의 난수를 반환(1은 제외)

 

Math.max(a,b,c...), Math.min(a, b, c...)

인수중 최대/최솟값을 반환

 

Math.pow(n,power)

n을 power번 거듭제곱한 값을 반환

 

 

출처 : ko.javascript.info/number#

'자바 스크립트' 카테고리의 다른 글

자바스크립트 배열  (0) 2020.12.13
자바스크립트 문자열  (0) 2020.12.12
자바스크립트 원시값의 메서드  (1) 2020.12.08
자바 스크립트 심볼형  (0) 2020.12.08
자바스크립트 옵셔널 체이닝 '?.'  (0) 2020.12.08

댓글