2015년 1월 27일 화요일

[JavaScript] 자바스크립트 Number 자료형

자바스크립트의 Number 데이터 타입

ECMAScript 에서 Number 자료형은 정수형(Integer Value)이든 소수형(Floating Point Value)이든 상관없이 IEEE-754 형식을 이용해서 저장한다. IEEE-754가 뭔지 잠시 짚고 넘어가자면

IEEE-754는 전기 전자 기술자 협회(IEEE)에서 개발한 컴퓨터에서 부동소수점를 표현하는 가장 널리 쓰이는 표준이다. ±0 등의 수와 무한, NaN 등의 기호를 표시하는 법과 이러한 수에 대한 연산을 정의하고 있다.

간단히 말하자면 0 과 1, 즉 이진법으로 이루어진 컴퓨터 연산체계에서 0 과 1 이상의 수들을 표현하는 표준 방식이라고 할 수 있다. IEEE-754 체계에서는 가장 첫번째 비트가 +,-인지를, 즉 그 수가 음수인지 양수인지를 나타내는데, 이러한 이유로 ECMAScript 에서는 0과 -0이 둘다 존재할 수 있다. 물론 0 == -0이라는 조건은 true(참)이다.

정수형


IEEE 32bits Single Precision 형식
IEEE 32bits Single Precision 형식

ECMAScript 는 굉장한 유연성과 높은 자유도를 가졌는데, 이러한 이유로 다양한 정수형 수들(8진수, 16진수)을 표현하기위한 다양한 문법들이 존재한다.
참고로 정수형 수들을 저장할 때는 32bits single precision 형식으로 저장된다는걸 기억하자. 즉 어떤 정수 값이든간에, 32비트 형식으로 저장된다는 것 이다. 위의 그림에 나와있는 방식으로 저장된다 생각하면 된다.


var integerNumber = 35; //integer 값을 선언할 때

//8진수를 표현할 때는 첫번째 자리의 숫자가 무조건 0 이여야 한다.
var octalNumber1 = 07; //8진수 07, 10진수로 환산하면 7
var octalNumber2 = 017; //8진수 017, 10진수로 환산하면 15
var octalNumber3 = 019; //3번째 자리의 수가 8진수에 없는 숫자인 9라 일반 10진수로 받들여지게 된다.
//하지만 8진수의 사용은, strict 모드에서 에러를 발생시키고, 몇몇 브라우져에서는 제대로 실행되지 않으므로 사용을 자제하자.

//16진수를 표현할 때에는 숫자 앞에 무조건 0x 를 붙인다.
var hexaNumber1 = 0x7; //16진수 07, 10진수로 환산하면 7
var hexaNumber2 = 0xA7; //16진수 A7, 10진수로 환산하면 167
var hexaNumber3 = 0xB35; //16진수 B35, 10진수로 환산하면 2869


하지만 결국 16진수나 8진수로 선언된 변수들도 연산시에는 다 10진수로 변환되니, 별다른 특별한 이유가 없으면 10진수를 사용하도록 하자.

소수형


IEEE 64bits Double Precision 형식
IEEE 64bits Double Precision 형식

ECAMScript에서의 소수형은 정수형과는 달리 64bits double precision 형식으로 저장된다. 바로 위의 그림과 같은 형식이다. 소수형 수들은 아래와 같이 선언되는데


var floatingNumber1 = 0.3; 
var floatingNumber2 = 1.47;
var floatingNumber3 = .7;//안 좋은 예제 1
var floatingNumber3 = 3.;//안 좋은 예제 2, 결국 3으로 자동 변환되 저장됨
var floatingNumber3 = 4.0;//안 좋은 예제 3, 4가 정수형으로 인식되서 32bit 형식으로 저장됨
var floatingNumber3 = 4.572e3;// = 4572, 많이 작거나 큰 숫자의 경우에는 e-notation을 이용 10의 몇 승으로 표현할 수 있다.
var floatingNumber3 = 4.572e-3;// = 0.04572
//ECMASCript 는 소수점아래로 0이 5개보다 많을 시에 무조건 e-notation을 이용한 표기법으로 수를 표현한다.
var testFloat = 0.0000006533;
console.log(testFloat); //6.533e-7


위와 같이 다양한 방식으로 선언되고 어싸인될 수 있는데, 몇가지 피해야할 방식들이 있다. ECMAScript에서 정수형은 32bits로 소수형은 64bits 로 표현되는 만큼, 소수형을 표현하는데는 정수형의 2배에 달하는 메모리를 사용해야 한다. 이러한 이유로 ECMAScript는 제대로된 형식이 아닌 소수형 수들은 무조건 integer로 인식 32bits 형식으로 저장하게 된다.

우선 안 좋은 예제 1은 작동은 하나, 최대한 피해야할 방법이다. 몇몇 Javascript 엔진에 따라서는 에러가 뜰 수도, 또는 0이나 1로 변환되서 저장될 수도 있다.
안 좋은 예제 2 같은 경우는 제대로 완성되지 않은 숫자라, 3으로 자동 변환되서 저장된다.
안 좋은 예제 3 같은 경우에는 숫자 4.0가 정수형으로 변환되서 32bit 형식으로 저장된다.

소수형을 이용한 연산을 할 때 조심해야할건, 무슨 일이 있어도 var1 + var2 = 0.6 같은 소수형 비교는 하면 안된다는건데, 이 이유는 IEEE-754의 정확성에 있다.

IEEE-754 방식은 그냥 일반 수를 표현할 때는 소수점 아래로 17번째 자릿수까지 완벽하게 정확하지만, 사칙연산시에 그 결과값의 정확성이 매우 떨어지기 때문이다.


var var1= 0.2; //Double Precision시에 0.20000000298023224라는 값으로 저장된다.

var var2= 0.4; //Double Precision시에 0.4000000059604645라는 값으로 저장된다.

console.log(var1 + var2 == 0.6); //false값이 프린트된다

var var3= 0.6; //Double Precision시에 0.6000000238418579라는 값으로 저장된다.

console.log(var1 + var2 == var3); //false값이 프린트된다


위와 같은 경우
var1 + var2 는 0.6000000089406967라는 결과를 도출하게되고, 0.6이라는 값(메모리내에는 0.6000000238418579라는 값으로 저장) 과 일치하나는 조건에서 false(거짓)값을 가지게 된다.
그러니 소수형 수의 연산값을 이용한 조건문은 절대로 쓰지 않도록 하자.

표현할 수 있는 수의 범위와 무한(Infinity) 값

ECMAScript에서 Number 자료형을 표현할 때 사용하는 비트수에 제한이 있다보니, 표현할 수 있는 수가 무한하지가 않다. 
최대로 표현가능한 수와 최소수는 아래와 같이 확인이 가능하다.


console.log(Number.MAX_VALUE); //양수의 최대값 
console.log(Number.MIN_VALUE); //양수의 최소값


만약 이에서 더 커지거나 작아지면 IEEE-754로 표현하는 한계를 넘으면 그 수는 Infinity 로 표현된다


console.log(Number.MAX_VALUE + Number.MAX_VALUE); //Infinity
console.log(- Number.MAX_VALUE - Number.MAX_VALUE); //-Infinity


그리고 Infinity 값은 Infinity를 제외한 다른 수와의 어떤 연산에서도 Infinity 값을 결과로 도출한다.
참고로 Infinity 값은 아래와 같이 불러올 수 있다.


console.log(Number.NEGATIVE_INFINITY + Number.POSITIVE_INFINITY); //NaN
console.log(Number.NEGATIVE_INFINITY + Number.MAX_VALUE); //-Infinity
console.log(Number.POSITIVE_INFINITY - Number.MAX_VALUE); //Infinity


NaN 값 이란?


간단하다. Not a Number 의 약자로 연산의 결과가 수가 아닐때 사용된다.
-Infinity + Infinity, 3/0 와 같이 결과가 숫자로 도출될 수 없을 떄 사용된다.


console.log(Number.NEGATIVE_INFINITY + Number.POSITIVE_INFINITY); //NaN
console.log(NaN + 3);//NaN이 포함된 연산은 언제나 결과가 NaN이다.

console.log(NaN == NaN); //false
//NaN값은 본인을 포함한 어떠한 값과도 Equal하지 않는다. 이러한 이유로 ECMAScript 에는 isNaN이라는 function이 있다

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


이 isNaN() function 은 주어진 파라미터를 Number 자료형으로 변환 시도를 해서, 성공적으로 변환이 되면 false 를 아니라면 true 값을 리턴하는 함수이다.
그러니 ECMAScript 의 자동변환으로 Number 자료형으로 변환될 수 있는 경우에는 false 값이 리턴된다.


console.log(isNaN(NaN)); //true 
console.log(isNaN(1)); //false 
console.log(isNaN("1")); //false 
console.log(isNaN("test")); //true
console.log(isNaN(true)); //false


타 자료형을 Number 자료형으로 변환시 

자바스크립트(ECMAScript)는 Number(), parseInt(), parseFloat() 함수등을 이용해 타 자료형을 Number 자료형으로 변환 할 수가 있다. 변환 값은 아래 표를 참고하자

Number() 함수를 사용해 타 자료형을 변환시



var num1 = Number("String");
var num2 = Number(true);
var num3 = Number(null);
var num4 = Number(undefined);
var num5 = Number(NaN);
var num6 = Number(new Object());


자료형
변환시 Number 값
01NaN숫자
Booleanfalsetrue해당 사항 없음해당 사항 없음
Undefined해당 사항 없음해당 사항 없음undefined해당 사항 없음
Nullnull해당 사항 없음해당 사항 없음해당 사항 없음
Number01NaN모든 숫자들
String"0" or """1","01""TEST", "0Tx34",등 다른 조건에 부합하지 않을 때따옴표 사이에 숫자밖에 없을 때 자동으로 수로 변환(16진수도 10진수로)
Object해당 사항 없음해당 사항 없음모든 object 타입해당 사항 없음


String 자료형의 Number 자료형으로의 변환에 대해 짧게 설명하자면, 

"0", "11", "055" 와 같이 스트링의 따옴표 사이에 숫자 밖에 없다면, 무조건 동일한 Number 값으로 변형된다. 숫자의 맨 앞에오는 0은 생략되고, 만약 따옴표안에 "0xAB"와 같이 16진수 수가 있다면 자동으로 10진수로 변환된다. 

Empty String, 빈 스트링 값 같은 경우에는 무조건 0으로 변환되고, 이를 제외한 모든 상횡에서는 다 NaN값으로 변환된다.

parseInt() 함수를 사용해 타 자료형을 변환시

parseInt() 함수는 Number 함수와 String 자료형 변환을 제외하고는 모두 똑같은 변환값을 가진다. 하지만 String 값의 경우에 캐릭터가 들어간 모든 String을 NaN 값 으로 변환하는 Number와 달리 첫자리가 숫자라면, 이어지는 숫자들까지 모두 Number 자료형(정수)으로 변환한다. 또한, 파라미터에 radix 를 설정해줄 경우에, 주어진 스트링을 2진수, 8진수, 16진수, 10진수로 인식하는것을 설정할 수도 있다

var num1 = parseInt("String");
var num1 = parseInt(true);
var num2 = parseInt(null);
var num3 = parseInt(undefined);
var num4 = parseInt(NaN);
var num5 = parseInt(new Object());
var num6 = parseInt("1110",2); //1110을 2진수로 인식, 10진수 14로 변환한다
var num7 = parseInt("17",8); //17을 8진수로 인식, 10진수 15로 변환한다
var num8 = parseInt("A3",16); //A3을 16진수로 인식, 10진수 163으로 변환한다
var num9 = parseInt("333",10); //10진수로 인식한다


자료형
변환시 Number 값
01NaN기타
Booleanfalsetrue해당 사항 없음해당 사항 없음
Undefined해당 사항 없음해당 사항 없음undefined해당 사항 없음
Nullnull해당 사항 없음해당 사항 없음해당 사항 없음
Number01NaN모든 숫자들,(소수일때 정수자리만 변환)
String"0" or """1","01""TEST", "Tx34",등 다른 조건에 부합하지 않을 때앞자리들이 숫자일 때는 앞자리들을 수로 변환("43TX8" -> 43)
만약 16진수라면 10진수로 변환("0xApp" -> 10)
Object해당 사항 없음해당 사항 없음모든 object 타입해당 사항 없음



parseFloat() 함수를 이용해 타 자료형을 변환시

parseFloat() 함수는 parseInt() 함수와 모든게 같으나, 32bits 정수형으로 변환하는 parseInt()함수와 달리 String 자료형 변환에서 소수형 수를 발견할 때 64bits 소수형으로 변환한다. 만약 정수형수라면 32bits 정수형으로 변환

var num1 = parseInt("String");
var num1 = parseFloat("0.44TQG"); //0.44
var num2 = parseInt("32BB"); //32(O), 32.0(X)

댓글 없음:

댓글 쓰기