서론
→ 왜 공부하게 되었는가?
- Javascript 는
int
,float
와 같은 다양한 숫자타입을 사용하는 것이 아닌 1 가지 숫자타입을 사용한다.
- 이 숫자타입의 값은
배정밀도 64비트 부동소수점
을 따른다.부동소수점
이라는 개념은 알지만배정밀도
라는 언어는 낯설어 찾아서 공부하게 되었다.
왜이러는걸까요?
console.log(0.1+0.2) // 0.30000000000000004 console.log(0.1+0.2 === 0.3) // false
단정밀도? 배정밀도?
- 단정밀도(single precision)는
32비트
를 사용하는 것을 이야기하며, 배정밀도(double precision)는64비트
를 사용하는 것을 이야기한다.
고정소수점? 부동소수점?
7.625
를 2진수로 표현하고자 할 때, 변환하면111.101
이 된다.
고정 소수점
.
을 기준으로111
은 정수부가 되며,101
은 소수부가 될 것이다.
- 부호는
+
이므로 부호 비트는0
이 된다. (-
이면1
)
- 단정밀도 고정소수점 을 사용한다면 아래와 같다.
0
|000_0111
00000000
|1010_0000
00000000
- 단정밀도(32비트) 가 주어졌을 때,
정수부
와소수부
의 비트할당량은 정해져 있는가?- 정수부(15비트), 소수부(16비트)로 나눠져있다?
NO
- 고정 소수점은 특정 숫자의 소수점의 위치를 고정하는 방식으로 앞 10개의 비트는 정수 부분을 표현하도록, 나머지 22개의 비트는 소수점 이하의 부분을 표현하도록 할 수 있다.
- 즉, 소수점 위치를 어디로 설정해야 하는지에 대해서는 정해진 답이 없으므로 사용자 임의대로 설정하면 된다.→
0
|000_0111
|1010_0000
00000000
00000000
- 단, 사용하는 수의 범위를 감안하여 오버플로우(Overflow) 가 발생하지 않도록 설정해야 한다.
- 정수부(15비트), 소수부(16비트)로 나눠져있다?
소수부
는 앞에서부터 채운다.
- 단정밀도(32비트) 가 주어졌을 때,
부동 소수점
111.101
을정규화
하여1.11101 * 2^2
로 나타낼 수 있다.- 2 진수를
1.xxxx..*2^n
꼴로 나타내는 것을정규화
- 2 진수를
- 단정밀도(32비트) 기준 맨 왼쪽 1 비트는 고정 소수점과 마찬가지로 부호 비트 이며, 이어지는 8 비트는 지수부, 나머지 23 비트는 가수부 로 표현된다.
0
|1000_0001
|1110_1000
00000000
00000000
0000000
- 배정밀도는 1 / 11 / 52 로 나뉘어진다.
바이어스(bias)
- 부동 소수점의
지수부
를 보며 지수는 2^2 니까, 지수 2 를 2진수로 바꾸면0000_0010
아닌가? 라고 생각이 들 수 있다.
- IEEE 754 표준에 따르면, 지수를 그대로 넣는 게 아닌,
바이어스
(bias) 라고 하는 지정된 숫자를 더한 다음 넣어야 한다고 한다.32
비트에서bias
는127
이며,64
비트에서bias
는1023
이다.
- 위 사례는
127+2 = 129
이므로,129
를 2진수로 표현한1000_0001
이 나온 것이다.
bias 숫자?
- 그렇다면
127
,1023
은 어디서 튀어나온 숫자일까?
- C언어 에서 쓰이는 8비트 정수형 처리 키워드인
char
로 설명하면char
는 8비트 변수이므로-128~127
까지의 숫자를 취급할 수 있다.- 0000_0000 : 0
- 0000_0001 : 1
- ...
- 0111_1111 : 127
- 1000_0000 : -128
- 이 부분이 왜
-128
인지 헷갈릴 수 있는데 일단은 이렇게 이해하고, 추후 포스팅하겠습니다.
- 이 부분이 왜
- 1000_0001 : -127
- ...
- 1111_1111 : -1
- 바이어스 표현법 은 아래와 같다.
- 0000_0000 : -127
- 0000_0001 : -126
- ...
- 0111_1111 : 0
- 1000_0000 : 1
- ...
- 1111_1111 : 128
- 바이어스 표현법에 따르면
0
이 되는 수가32비트
기준127
이기 때문에 바이어스 상수가127
이 된다.
- 왜 바이어스 표현법을 쓰는가?
- 지수 비트에도
부호 비트
를 넣어서음의 지수를 표현하는 것
보다 더 쉽게 구현할 수 있음
- 지수 비트에도
왜이러는걸까요? → Answer
- 위 표현법에 따르면
0.1
은 부동 소수점 방식으로 제대로 표현하기 어렵다.비순환소수
의 문제로, 2 진수로 아무리 나누어도 무한소수가 되기 때문이다.- 0.1 * 2 → 0.2 : 0.0
- 0.2 * 2 → 0.4 : 0.00
- 0.4 * 2 → 0.8 : 0.000
- 0.8 * 2 → 1.6 : 0.0001
- 0.6 * 2 → 1.2 : 0.00011
- 0.2 * 2 → 0.4 ... (무한 반복)
- 따라서
0.1
을 제곱하여도0.01
이 되지 않는다.
const a = 0.1 a.toString(2) // "0.0001100110011001100110011001100110011001100110011001101"
- 위에서 오는 부정확성 때문에
0.1+0.2
와 같은 문제가 생길 수 있다
참고
Uploaded by Notion2Tistory v1.1.0