WEB/Javascript

[JAVASCRIPT.INFO] 5.2 숫자형

dev-olive 2023. 1. 2. 22:35

5.2 숫자형

일반적인 숫자

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

let billion = 1e9;    // 10억, 1과 9개의 e
alert(7.3e9);        // 73억
let ms = 0.000001;
let ms = 1e-6;        // 1에서 왼쪽으로 6번 소수점 이동

16진수, 2진수, 8진수

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

alert(0xff);        // 255, 대소문자 가리지 않음

let a = 0b11111111;        //255의 2진수
let b = 0o377;        // 255의 8진수
alert( a== b );     // true;

toString(base)

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

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

사용할 수 있는 base의 최댓값은 36이다.

123456..toString(36)은 숫자를 대상으로 메서드 toString을 직접 호출하고 싶을 때 ..을 붙인다. (123456).toString(36)도 가능하다

부정확한 계산

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

alert(1e500);        // Infinity;

정밀도 손실

0.10.2의 합은 0.3이 되지 않는다. 숫자는 0과 1로 이루어진 이진수로 변환되어 연속된 메모리 공간에 저장된다. 그런데 10진법을 사용하면 쉽게 표현할 수 있는 분수가 이진법으로 표현하면 무한 소수가 된다.

IEEE-754에선 가능한 가장 가까운 숫자로 반올림하는 방법을 사용해 이런 문제를 해결하지만, 반올림 규칙을 적용하면 발생하는 '작은 정밀도 손실'을 볼 수는 없지만 실제로 손실은 발생한다.

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

정밀도 손실을 눈으로 볼 수 있다.

문제를 해결하기 위해서는 toFixed(n)메서드를 사용해 어림수를 만드는 것이다.

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

숫자에 임시로 100을 곱하여 정수로 바꾸고, 원하는 연산을 한 후 다시 100으로 나누는 것도 하나의 방법이 될 수 있다. 하지만 마지막에 나눗셈이 들어가기 때문에 소수가 다시 등장할 수 있다는 단점이 있다. 무한 소수를 방지하는 완벽한 방법은 사실 없다. 필요할 때마다 '꼬리'를 잘라 어림수를 만드는 방법뿐이다.

isNaN과 isFinite

  • Infinity-Infinity -그 어떤 숫자보다 큰 혹은 작은 특수 숫자 값
  • NaN -에러를 나타내는 값

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

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

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

    NaNNaN 자기 자신을 포함하여 그 어떤 값과도 같지 않다는 점에서 isNaN함수가 필요하다

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

    alert( isFinite("15") )        // true
    alert( isFinite("str") )    // false
    alert( isFinite(Infinity) )    // false
    

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

Object.is

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

  1. NaN을 대상으로 비교할 때: Object.is(NaN, NaN) === true임.
  2. 0-0이 다르게 취급되어야 할 때: Object.is(0, -0) === false임. 숫자를 나타내는 비트가 모두 0이더라도 부호를 나타내는 비트는 다르므로 다른 값

이 두 케이스를 제외하곤 결과가 같다.

parseInt와 parseFloat

단항 덧셈 연산자 + 또는 Number()를 사용하여 숫자형으로 변환할 때, 피연산자가 숫자가 아니면 형 변환에 실패한다.

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

parseInt, parseFloat은 숫자만 추출해야 할 경우에 사용한다. 두 함수는 불가능할 때까지 문자열에서 숫자를 읽는다. 읽을 수 있는 숫자가 없을 때 NaN을 반환한다.

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

alert(parseInt('12.3'))        // 12
alert(parseFloat('12.3.4')) // 12.3

alert(parseInt('a123'));        // NaN

parseInt(str, radix)

두 번째 매개변수는 원하는 진수를 지정해 줄 때 사용한다.

alert(parseInt('0xff', 16));        // 255