티스토리 뷰
포스팅에 앞서 내용이 틀릴 수 있습니다.
해당 부분 지적 감사히 받습니다.
프로그래밍을 하다 보면 당연히 소수점을 다루게 되는 일이 있다.
이럴 때 우리는 실수 자료형 변수에 이 값을 담아 사용하는 방법을 선택한다.
하지만 이럴경우 문제가 발생될 수 있다.
아니 실수 자료형에 실수를 담았는데 무엇이 문제가 될 수 있다는 것인가?
예시를 보자.
우리는 당연히 0.1 + 0.2가 0.3 인 것을 알고 있다.
하지만 자바스크립트의 출력 결과는 0.1 + 0.2 == 0.3의 값이 false가 나왔다.
어떻게 된것일까?
이 문제의 근본은 램(RAM)에 있다.
램은 유한한 공간을 갖고 있으며, 각 변수를 저장하는 공간 또한 필연적으로 유한하다.
물론 이 문제의 경우 램의 공간이 무한하다 해도 실수부를 이진수로 변환하는 과정 중 순환 소수에 해당하는 값이 있으면 같은 문제가 발생한다. ex) x.1
우리가 사용하는 대부분의 프로그램에서는 실수의 이진수 표현을 IEEE 754 표준의 부동 소수점 방식을 채택하고 있다.
그렇다면 IEEE 754 표준의 부동 소수점 방식에 대해 알아보자.
메모리 공간이 32 bit 일 땐, (1 + 8 + 23) bit로 분리되어 메모리를 차지한다.
- 부호부 1 bit
- 지수부 8 bit
- 가수부 23 bit
메모리 공간이 64 bit 이면 (1 + 11 + 52) bit 로 분리된다.
- 부호부 1 bit
- 지수부 11 bit
- 가수부 52 bit
부호부는 0일 때 양수, 1일 때 음수이므로 헷갈리지 않도록 주의하자.
메모리 공간의 크기에 따라 각 부동 소수점 방식의 이름이 달라진다.
- 32bit일 때, 단정도 부동 소수점 방식 -> float
- 64bit일 때, 배정도 부동 소수점 방식 -> double
메모리 공간을 차지하는 것이 가장 큰 차이점이지만, 반드시 알아둬야 할 것이 하나 더 있다.
바로 bias 값이다
- 32bit = bias 고정 값 127
- 64bit = bias 고정 값 1023
bias 값은 부동 소수점을 계산할 때 반드시 필요한 값이다.
이제 컴퓨터에서 배정도 부동 소수점 방법으로 실수값을 어떻게 저장하는지 알아보자.
예제 : 5.1
정수 5의 경우 이진수로 나타냈을 경우 101이다.
이제 소수점 0.1을 이진수로 나타내보자.
0.1 * 2 = 0
0.2 * 2 = 0
0.4 * 2 = 0
0.8 * 2 = 1
0.6 * 2 = 1
0.2 * 2 = 0
0.4 * 2 = 0
0.8 * 2 = 1
0.6 * 2 = 1
0.2 * 2 = 0
.
.
.
0.00011001100...으로 순환소수가 된다.
아무리 배정도 방식의 메모리 공간이 52bit로 커도 순환 소수를 담기엔 너무나도 작은 공간이다.
따라서 52bit를 초과하는 뒷부분은 잘리게 되어있다.
이 부분에서 아까 예시로 보았던 값의 오차가 발생하는 것이다. ex) 0.1 + 0.2! = 0.3
다시 본론으로 와서 어떻게 메모리에 적재되는지 보자.
5.1은 이진수로 101.000110011...이다.
정규화를 시킨다.
정규화하는 방법은 소수점을 한자리만 남겨두고 왼쪽으로 옮긴다.
옮긴 bit 수만큼 2^n 원래값에 더해준다.
결과
1.01000110011... x 2^2
여기서 2^2의 지수값은 2이다.
지수값에 bias 값을 더해준다.
2 + 1023 = 1025
1025를 다시 2진수로 변환한다.
10000000001 (2) = 1025 (10)
이 값이 바로 램의 지수부에 저장이 되는 것이다.
이제 가수부에는 어떤 값이 저장이 될까?
바로 상단 결과에 있는 1.01000110011... x 2^2에서 소수점 아래 부분이 저장이 된다.
이렇게 가수부에 저장되는 과정을 보니 왜 오차가 발생하는지 유추할 수 있게 된다.
저장된 전체 값을 보자
가수부가 순환소수이니 52bit를 초과하는 값은 자연스레 버려지게 된다.
정확하게 이 부분에서 오차가 발생하는 것이다.
최종적으로 배정도 부동 소수점 방식에서는 실수 값 5.1이 메모리에 위처럼 적재된다.
이러한 오차를 해결하기 위해선 어떤 방식이 필요할까?
아주 간단하게 해결할 수 있다.
바로 실수를 안 쓰면 된다
5.1에 10을 곱하면 된다
그러면 51이 될 것이고, 나중에 이 값이 필요할 때 다시 10으로 나누면 정확히 5.1로 구하여 쓸 수 있다.
- Total
- Today
- Yesterday
- 코딩테스트 준비
- 백준 피보나치 수열
- 프로그래머스 상품을 구매한 회원 비율 구하기 파이썬
- 김영한 실전 자바 중급
- webhacking.kr
- 상속
- samron
- samron3
- 김영한 실전 자바 기초
- los 15단계
- ys.k
- zixem
- 코딩테스트
- java
- 프로그래머스 상품을 구매한 회원 비율 구하기
- 백준
- 백준 피보나치
- lord of sql
- 프로그래머스
- 스프링
- 상품을 구매한 회원 비율 구하기 파이썬
- 김영한
- 자바
- static
- Los
- 김영한 실전 자바 기본
- los 15
- extends
- spring
- 기술스택
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |