Frontend/JS.info 정리

자료구조와 자료형 - 숫자형

Creative_Lee 2022. 1. 18. 18:08

모던 자바스크립트는 숫자를 두 가지 자료형으로 나타냅니다.

 

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

 

2. 일반적인 숫자는 2의 53제곱 이상이거나 -2의 53제곱 이하일 수 없다는 제약 때문에  
    Bigint 라는 자료형이 만들어졌습니다.

 


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

 

0이 연속해서 많이 들어가는 숫자를 표현할 때 다음과 같은 방법을 사용합니다.

 

 

큰 수를 표현할 때

console.log(1e10) // 10000000000

1 * 10의 10제곱

e 왼쪽의 수에 
10에 e 오른쪽의 수로 거듭제곱한 수를 곱합니다.

 

작은 수를 표현할 때

console.log(1e-5) // 0.00001

1 / 10의 5제곱

e 왼쪽의 수에 
10에 e 오른쪽 음수의 절댓값으로 거듭제곱한 수로 나눕니다.

 

16진수

console.log(0xFF) // 255

색을 나타낼때 자주 보게 될 16진수

16,8,2 진법 외에 진법을 사용하려면 함수 parseInt를 사용해야 함

 

 

toString(base)

num.toString(base) 메소드는

base에 기입한 진법으로 num을 포현해 문자형으로 리턴합니다.

let num = 10

console.log(num.toString(2)) // 1010

 

 


Math의 내장함수( 어림수 )

 

Math.floor

소수점 첫째 자리에서 내림 합니다.

ex) 3.1 = 3 ,  -1.1 = -2

 

Math.ceil

소수점 첫째 자리에서 올림 합니다.

ex) 3.1 = 4 ,     -1.1= -1

 

Math.round

소수점 첫째 자리에서 반올림 합니다.

ex) 3.45 = 3,    -1.5 = -2,     -1.4 = -1

 

Math.trunc

소수를 무시합니다.

ex) 3.1485... = 3,    -1.516132.. = -1

 

 

원하는 소수점 자리에서 어림수 하는법

 

1. 10을 남기고 싶은 소수점 자리 수로 거듭제곱한 수를 곱하고 다시 나누기

 

ex) 한 자리 수 = 10 * 1 =10,  두 자리 수 = 10 * 10 = 100, 세 자리 수 = 10 * 10 * 10 = 1000

 

let num = 1.23456789

console.log(Math.round(num*10)/10) // 1.2

소수 한 자리수를 원하면 10을 곱하고 빼주면 된다.

 

 

2. toFixed(n) 사용하기

 

num.toFixed(n) 메소드는 num을  n번째 자리에서 반올림 한 값을 문자열로 반환합니다.

let num = 1.23456789

console.log(num.toFixed(4)) // "1.2346" --> 문자열을 반환합니다.

+ 단항 플러스 연산자 혹은 Number() 를 사용하여 숫자열로 변환하여 사용합니다.

 


 

 

부정확한 계산

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

64비트 중 52비트는 숫자를 저장하는 데 사용되고,

11비트는 소수점 위치를(정수는 0),

1비트는 부호를 저장하는 데 사용됩니다.

 

 

Infinity

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

console.log( 1e1000 ) // Infinity

 

 

정밀도 손실

let num = 0.1 + 0.2

console.log(num) // 0.30000000000000004

이상합니다.

위와 같은 결과의 이유는 다음과 같습니다.

 

10진법에서

1을 10의 거듭제곱으로 나눈 수( 1/10, 1/100 등등 ) 는 표현할 수 있지만,

1을 3의 거듭제곱으로 나눈 수( 1/3, 1/9 등등) 는 정확하게 나타낼 수 없습니다. ( 무한 소수 )

 

마찬가지로~!

 

2진법에서

1을 2의 거듭제곱으로 나눈 ( 1/2, 1/4 등등) 은 잘 작동하지만,

1을 2의 거듭제곱이 아닌 값으로 나눈 값들은 무한 소수가 되어버립니다.

 

숫자는 0과 1로 이루어진 2진수로 변환되어 메모리 공간에 저장되기 때문에

0.1 + 0.2 와 같은 숫자를 2진법에서 정확하게 저장할 수 없어 위와 같은 현상이 발생합니다.

 

 

우리가 쓰는 64비트 IEEE-754에서는 위와같은 무한 소수들을 가장 가까운 숫자로 반올림 하는 방법을 사용해 이런 문제를 해결합니다.여기서 반올림을 통해 발생하는 약간의 오차로 인해 정밀도에 문제가 생기는 것입니다!

 

 

 

해결법

위와 같은 문제의 해결책으로 종전에 설명한 toFixed() 메소드를 사용할 수 있습니다.

let num = 0.1 + 0.2

console.log(num.toFixed(2)) // '0.30'

toFixed 메소드는 문자열을 리턴하기 때문에 0.30 과 같이 0이 맨 뒤에 붙는 것도 가능합니다.

 

자바스크립트는 정밀도의 손실이 일어나도 오류를 발생시키지 않기 때문에

무한소수가 발생 할 수 있는 상황에서는 위와 같은 해결법을 통해 미리 꼬리를 자르면 되겠습니다.

 


isNaN, isFinite

 

Infinity와 -infinity : 그 어떤 숫자보다 큰, 작은 특수 숫자

NaN : 숫자와 관련된 연산에서 에러를 나타내는 값

 

위 두 특수 숫자는 숫자형 이지만 정상적인 숫자는 아닙니다!

고로 정상적인 숫자와 구분하기 위한 특별한 함수가 존재합니다.

 

 

isNaN( )

인수를 숫자로 변환하고 NaN인지 테스트함

console.log( isNaN(NaN) ); // true
console.log( isNaN("str") ); // true

위의 함수를 보다보면 꼭 필요할까 ? ===NaN 비교를 하면 되지 않을까? 생각이 듭니다.

 

하지만 꼭 필요합니다!

console.log( NaN == NaN ); // false
console.log( NaN === NaN ); // false

NaN은 자기 자신을 포함한 모든 값들과 같지 않기 때문입니다!

 

isFinite( )

인수를 숫자로 변환하고 NaN, Infinity, -infinity 가 아닌 일반숫자일 경우 true를 리턴함

* finite = 유한한 , 유한한지 확인하는 함수이다.

console.log( isFinite(123) ); // true
console.log( isFinite('123') ); // true
console.log( isFinite('안녕하신가') ); // false
console.log( isFinite(Infinity) ); // false
console.log( isFinite(-Infinity) ); // false

 

isFinite() 로 문자열이 일반 숫자인지 검증할 수 있습니다.

let isFiniteNum = +prompt('숫자를 입력하세요','시른데')

console.log(isFinite(isFiniteNum)) // false

 

* 빈 문자열이나 공백만 있는 문자열은 isFinite를 포함한 모든 숫자 관련 내장 함수에서 0으로 처리합니다!

 


 

Object.is

NaN을 대상으로 비교할때나 0과 -0이 다르게 취급되어야 할때는

Object.is( ) 메소드로 값을 비교합니다.

console.log(0 === -0) // true
console.log(Object.is(0 , -0)) // false

0과 -0이 다르게 취급되어야 하는 케이스에는 Object.is() 를 사용합시다!

console.log(NaN === NaN) // false
console.log(Object.is(NaN , NaN)) // true

NaN 끼리 비교해야 하는 케이스에는 Object.is() 를 사용합시다!

 

parseInt, parseFloat

단항 덧셈 연산자 + 나 Number() 를 사용해 값을 숫자형으로 바꿀때 적용되는 규칙은 엄격합니다.

피연산자가 숫자가 아니면 형 변환이 실패하고 NaN을 반환합니다...

console.log( +'100원' ) // NaN
console.log( +'100' ) // 100

console.log( Number('100원' )) // NaN
console.log( Number('100' )) // 100

그럼 숫자와 문자가 섞여있는 값에서 숫자만 추출하고 싶을때는 어떻게 해야할까요?

 

이 때 parseInt 와 parseFloat를 사용합니다.

두 함수는 불가능할 때 까지 문자열에서 숫자를 읽습니다.

읽는 도중 오류가 발생하면 그 지점까지의 숫자를 반환합니다.

 

parseInt는 정수, parseFloat는 부동 소수점 숫자를 리턴합니다~

console.log( parseInt('100원 인데용'))  // 100 
console.log( parseFloat('10.32달러 인데용')) // 10.32

console.log( parseInt('100.5원 인데용'))  // 100 
console.log( parseFloat('10.32.22달러 인데용')) // 10.32

parseInt는 정수 컷 ! parseFloat는 소수까지 컷 !

 

 

 

Math의 내장함수 ( 수학 관련, 상수 )

 

Math.random( )

0과 1사이의 난수를 반환합니다. ( 0은 나오는데 1은 나오지 않아유..)

console.log(Math.round(Math.random()*10)) // 0 ~ 10 까지 정수를 랜덤하게 리턴 !

 

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

인수 중 최대/최솟값을 리턴합니다.

console.log(Math.max(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // 10
console.log(Math.min(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // 1

let numArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(Math.max(...numArr))

max,min의 인수로는 값만 들어가야해서 [ ]를 인수로 쓰려면 ...으로 괄호를 제거해주세요

 

Math.pow( n , power )

n을 power번 거듭제곱 한 값을 리턴합니다.

console.log(Math.pow(3,3)) // 27

 

 

 

챕터 요약!

 

1.  0이 많이 붙은 숫자는 e를 사용해 간단하게 나타낼 수 있다.
     ex ) e 다음 숫자는 0의 갯수 ---> 5661e5 = 566,100,000  ( 0이 5개 ) 
     ex ) e 다음 음수일 경우 절댓값 만큼 거듭제곱한 숫자로 나눔 ---> 1515e-5 = 0.01515 ( 1515/100000 ) 

 

2.  js는 특별한 변환 없이 16진수, 8진수, 2진수 를 지원한다.

 

3. parseInt( str, base ) 는 str을 base진수로 바꿔준다!

 

4. num.toString( base ) 는 숫자를 base진수로 바꾸고 문자열로 리턴한다!

 

5. parseInt, parseFloat 로 숫자와 문자가 같이 있는 값에서 숫자를 추출할 수 있다.

   각 메소드는 정수, 부동 소수점 단위로 숫자를 읽어나가고 오류가 발생하면 그때까지의 숫자를 리턴한다.

 

6. Math의 소수처리 메소드

   Math.floor : 내림

   Math.ceil : 올림

   Math.round : 반올림 
   Math.trunc : 소수 무시 정수 리턴
   모두 어림수를 구할 수 있다.

   

 

7. num.toFixed( precision ) 는 num을 반올림하여 precision 자릿수 까지 문자열로 리턴

 

8. 소수에서 발생하는 정밀도 손실을 미연에 방지하자.

 

 

 

 

 

기본이 중요하다.