5.2 숫자형
숫자형
모던 JS에서 숫자를 나타내는 두가지 자료형
1. 일반적인 숫자는 '배정밀도 부동소수점 숫자(double precision floating number)'로 알려진 64비트 형식의 IEEE-754에 저장
2. 임의의 길이를 가진 정수 BigInt, 일반적인 숫자의 범위 2-53 ~ 253 밖의 숫자
숫자를 입력하는 다양한 방법
let billion = 1000000000; //0의 갯수가 많아서 오류가 생길 수 있음
let billion = 1e9; // 10억, 1과 9개의 0
alert( 7.3e9 ); // 73억 (7,300,000,000)
'e' 의 오른쪽에 오는 수만큼 10의 거듭제곱
1e3 = 1 * 1000
1.23e6 = 1.23 * 1000000
1마이크로초(백만 분의 1초)
let ms = 1e-6; // 1에서 왼쪽으로 6번 소수점 이동
'e' 의 오른쪽에 음수가 있으면 음수의 절대값만큼 10을 거듭제곱한 수로 나눔
16진수, 2진수, 8진수
alert( 0xff ); // 255
alert( 0xFF ); // 255 (대·소문자를 가리지 않으므로 둘 다 같은 값을 나타냅니다.)
16진수 : 0x / 2진수 : 0b / 8진수 : 0o
let a = 0b11111111; // 255의 2진수
let b = 0o377; // 255의 8진수
alert( a == b ); // true, 진법은 다르지만, a와 b는 같은 수임
JS는 2, 8, 16진법을 지원함, 이 외의 진법은 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, A~F 사용
- base=2 : 비트 연산 디버깅에 주로 사용, 숫자0 또는 1
- base=36 : 사용할 수 있는 base 중 최댓값으로 0~9, A~Z 를 사용해 숫자 표현, url을 줄이는 것과 같이 숫자로 된 긴 식별자를 짧게 줄일때 유용 ??? url을 줄이는것..??? 예시 이해못함
alert( 123456..toString(36) ); // 2n9c
! 점 두개와 메서드 호출
숫자를 대상으로 메서드 toString을 직접 호출할 때 ..를 붙임
12345.toSting(36)처럼 점을 하나만 사용하면 첫번째 점 이후는 소수부로 인식되어 error, 점을 하나 더 추가하면 JS는 소수부가 없다고 판단하고 함수 호출
(12345).toString(36)도 가능
어림수 구하기
Math.floor 소수점 첫째 자리에서 내림(버림) ex) 3.1 -> 3, -1.1 -> -2
Math.ceil 소수점 첫째 자리에서 올림 ex) 3.1 -> 4, -1.1 -> -1
Math.round 소수점 첫째 자리에서 반올림 ex) 3.1 -> 3, 3.6 -> 4, -1.1 -> -1
Math.trunc(ie x) 소수부 무시 ex) 3.1 -> 3, -1.1 -> -1
소수점 n번째 기준으로 어림수 구하기
1. 곱하기와 나누기
10의 거듭제곱 수를 곱한 후 원하는 어림수 내장함수 호출하고 다시 나누기
let num = 1.23456;
alert( Math.floor(num * 100) / 100 ); // 1.23456 -> 123.456 -> 123 -> 1.23
2. 소수점 n번째 수까지의 어림수를 구한후 문자형으로 반환하는 toFixed(n) 메서드 사용
toFixed는 Math.round와 유사하게 가장 가까운 값으로 올림 혹은 버림,
반환값이 문자열이라 소수부의 길이가 인수보다 작으면 끝에 0추가
let num = 12.34;
alert( num.toFixed(1) ); // "12.3"
let num = 12.36;
alert( num.toFixed(1) ); // "12.4"
let num = 12.34;
alert( num.toFixed(5) ); // "12.34000", 소수부의 길이를 5로 만들기 위해 0이 추가되었습니다.
+num.toFixed(5)처럼 단항 덧셈 연산자를 앞에 붙이거나 Number()를 호출하면 숫자를 숫자형으로 변환 가능
부정확한 계산
숫자는 내부적으로 64비트 형식 IEEE-754으로 표현되기때문에 숫자를 저장하려면 정확히 64비트가 필요,
64비트 중 52비트는 숫자 저장, 11비트는 소수점 위치 저장(정수는 0), 1비트는 부호 저장
숫자가 너무 커질경우 64비트 공간이 넘쳐서 infinity로 처리
alert( 1e500 ); // Infinity
정밀도 손실(loss of precision)
alert( 0.1 + 0.2 == 0.3 ); // false
alert( 0.1 + 0.2 ); // 0.30000000000000004
숫자는 0과 1로 이루어진 이진수로 변환되어 연속된 메모리 공간에 저장되는데 0.2, 0.2와 같은 분수는 이진법으로 무한 소수가 되므로 IEEE-754 에서 가능한 가장 가까운 숫자로 반올림
alert( 0.1.toFixed(20) ); // 0.10000000000000000555
두 숫자를 더하게되면 정밀도 손실도 같이 더해짐
! JS뿐만이 아닙니다
JS와 동일한 숫자 형식을 사용하는 PHP, Java, C, Perl, Ruby 에서 같은결과 발생
해결
toFixed(n)메서드를 사용해 어림수 만들기
문자열을 반환하기 때문에 소수점 다음 숫자는 항상 2개
let sum = 0.1 + 0.2;
alert( sum.toFixed(2) ); // 0.30
단항 덧셈 연산자를 사용하여 다시 숫자형으로 강제 변환
let sum = 0.1 + 0.2;
alert( +sum.toFixed(2) ); // 0.3
임시로 10의 거듭 제곱수 곱하기, 연산 후 다시 나누기
소수 대상의 연산보다 에러가 적지만 결과값에서 수소발생 가능
alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001
소수점 아래를 완전히 차단해야하는 경우는 어림수를 만드는 방법 뿐
! 흥미로운 발견
// 숫자가 스스로 증가하네요!
alert( 9999999999999999 ); // 10000000000000000이 출력됩니다.
숫자를 저장할 때 사용되는 64비트 중 실제 숫자를 저장하는 52비트의 저장공간 부족으로 최소 유효 숫자(the least significant digit)가 손실되는 정밀도 손실 발생, JS에서 오류가 발생하지는 않음
! 두 종류의 0
JS에서 숫자의부호가 단일 비트에 저장되는데 0을 포함한 모든 숫자를 부호에 설정하거나 설정하지 않을 수 있음, 연산에서의 차이는 두드러지지 않는 편
isNaN과 isFinite
- Infinity와 -Infinity 그 어떤 숫자보다 큰 혹은 작은 특수 숫자값
- NaN 에러를 나타내는 값
두 특수 숫자는 숫자형에 속하지만 '정상적인' 숫자형이 아니므로 정상 숫자와 구별하기 위한 특별한 함수 존재
- isNaN(value) : 인수를 숫자로 변환한 다음 NaN인지 테스트
alert( isNaN(NaN) ); // true
alert( isNaN("str") ); // true
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이기 때문입니다.
문자열이 일반숫자인지 검증하는데 사용
let num = +prompt("숫자를 입력하세요.", '');
// 숫자가 아닌 값을 입력하거나 Infinity, -Infinity를 입력하면 false가 출력됩니다.
alert( isFinite(num) );
빈 문자열이나 공백만 있는 문자열은 isFinite를 포함한 모든 숫자 관련 내장함수에서 0으로 취급
! Object.is와 비교하기
Object.is는 === 처럼 값을 비교할 때 사용되는 특별한 내장 메서드로 ===보다 더 신뢰할 수 있는 결과를 보여주는 경우가 있음
1. NaN을 대상으로 비교할 때 : Object.is(NaN, NaN) === true
2. 0과 -0이 다르게 취급되어야 할 때 : Object.is(0, -0) === false
이 외의 경우에서는 Object.is(a, b)와 a===b 의 결과는 동일, 비교 결과가 정확해야 하는 경우 Object.is 사용, Object.is에서 사용되는 비교방식을 SameValue로 부름
parseInt와 parseFloat
단항 덧셈 연산자 + 또는 Number()를 사용하여 숫자형으로 변형할 때 적용되는 규칙은 엄격하여 피연산자가 숫자가 아닐 경우 형 변환 실패
alert( +"100px" ); // NaN
문자열의 처음 또는 끝의 공백을 무시할 때는 규칙적용x
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, 두 번째 점에서 숫자 읽기를 멈춥니다.
읽을 수 있는 숫자가 없는 경우 NaN반환
alert( parseInt('a123') ); // NaN, a는 숫자가 아니므로 숫자를 읽는 게 중지됩니다.
! 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.random() : 0과 1 사이의 난수 반환(1 제외)
alert( Math.random() ); // 0.1234567894322
alert( Math.random() ); // 0.5435252343232
alert( Math.random() ); // ... (무작위 수)
Math.max(a, b, c..) / Math.min(a, b,c..) : 인수 중 최대/ 최솟값 반환
alert( Math.max(3, 5, -10, 0, 1) ); // 5
alert( Math.min(1, 2) ); // 1
Math.pow(n, power) : n을 power번 거듭제곱한 값 반환
alert( Math.pow(2, 10) ); // 2의 10제곱 = 1024
요약
0이 많이 붙은 큰 숫자 요약 방법
- 0의 개수를 'e'뒤에 추가 ex) 123e6 = 123000000
- 'e' 다음에 음수가 오면 음수는 절댓값만큼 10을 거듭제곱한 수로 나눔 ex) 123e-6 = 0.000123
다양한 진법 사용
- JS는 특별한 변환없이 16진수(0x), 8진수(0o), 2진수(0b)를 바로 사용하도록 지원
- parseInt(str, base)를 사용하면 str을 base진수로 바꿔줌(단 2<=base <= 36)
- num.toString(base)는 숫자를 base진수로 바꾸고, 이를 문자열 형태로 반환함
단위가 있는 값을 숫자로 변환하기
- parseInt/parseFloat를 사용하면 문자열에서 숫자만 읽고 읽은 숫자를 에러가 발생하기 전에 반환하는 '약한' 형변환
소수를 처리하는데 쓰이는 메서드
- Math.floor, Math.ceil, Math.trunc, Math.round, num.toFixed(precision)를 사용하여 어림수 구하기
- 정밀도 손실에 주의
'JS > [web] 코어 JS 튜토리얼' 카테고리의 다른 글
[코어 JS] 5.4 - 배열 (0) | 2021.10.23 |
---|---|
[코어 JS] 5.3 - 문자열 (0) | 2021.10.23 |
[코어 JS] 5.1 - 원시값의 메서드 (0) | 2021.10.12 |
[코어 JS] 4.8 - 객체를 원시형으로 변환하기 (0) | 2021.10.11 |
[코어 JS] 4.7 - 심볼형 (0) | 2021.10.11 |