-
실수 계산에서 오차가 생기는 이유프로그래밍 기초 공부 2022. 11. 17. 00:59
[ 대표적인 예 ]
- 자바스크립트 소숫점 계산 오류
let a = 0.1; let b = 0.2; console.log(a+b); // 0.30000000000000004
0.1과 02.를 더하면 0.3이 나와야하는데 실제로 코드를 작성하면 그렇지 않은 결과가 나옴
자바스크립트 뿐 아니라 PHP, C, Java, Python등 많은 언어에서 오류가 발생함[ 원인 ]
-> 컴퓨터는 우리가 익숙하게 사용하는 10진법과 달리 2진법을 사용해 계산
-> 몇몇 소수의 경우에는 10진법을 2진법으로 변환할 때 무한소수가 되어버림
-> 숫자는 컴퓨터내에서 64비트 형식 IEEE-754로 표현됨, 정확한 숫자를 저장하려면 정확히 64비트가 필요
64비트 중 52비트는 숫자를 저장하는 데 사용, 11비트는 소수점 위치, 1비트는 부호를 저장하는 데 사용
-> 무한소수가 되는 경우 64비트를 초과
-> 저장공간의 한계로 인해 무한소수를 유한소수로 바꿈
-> 이러한 과정에서 미세한 오차가 생김
-> 계산 오류
[ 오차 예시 ]
float와 double의 사용
- 문제를 풀 때 float보다 double형 변수를 쓰는게 좋음
- double형 변수까지는 하드웨어로 계산되기 때문에 많이 느려지지 않지만, 정확도가 엄청나게 높아지기 때문
- float의 상대오차는 약 10^-7 정도이고, double의 상대 오차는 약 10^-15 정도
정수가 들어있는 실수형 변수를 정수로 캐스팅
- 1을 double 변수에 대입하면 0.99999..와 같은 수가 됨
- 이 변수를 그대로 정수 캐스팅하면 0이 됨
- 보통의 경우에는 1e-6 ~ 1e-9 정도를 더해서 캐스팅을 하거나, 정수형 변수만을 사용하여 연산을 하기도 함
비교 연산을 할 때에 등호 사용
- 실수형 변수는 오차가 있기 때문에 같은 값을 가져야만 하는 상황에서도 다른 값일 때가 매우 많음
- 그렇기 때문에 비교연산을 할 때 등호 사용을 하면 안됨
- 보통의 경우 abs(A-B) < EPS 로 함, EPS는 1e-6~1e-9 정도로 정함
큰 수를 다룰 때, 매우 작은 상수값을 사용
- double형의 상대 오차는 10^-15
- 즉, 10^15를 double형 변수에 대입하면 오차가 1의 자리에서 발생할 수 있음
- 즉, 조건문으로 (A-B) < 1e-6 을 사용했는데, A, B가 10^11 크기 정도라면, (A-B) < 1e-6과 A == B는 똑같은 결과임
- double형 변수를 가지고 넓은 범위의 이진탐색을 돌릴 때 자주 발생하는 문제이고,
- 100~200번 정도만 반복한다던가, 상대오차가 몇 이하일 때 반복문을 빠져나오는 식으로 해결
큰 수에 작은 수를 더할때
- 10^20 정도 되는 double형 변수에 1을 10^20번 더해도 값이 변하지 않음
- 또는, 큰 수에 작은 수를 더할 때 작은 수의 정밀한 부분이 사라지기 때문에 오차가 커질 수 있음
- 보통은 작은 수끼리 더한 뒤에 큰 수에 더하는 방법으로 해결이 가능
'프로그래밍 기초 공부' 카테고리의 다른 글
Serverless란? (0) 2022.11.26 Microservice Architecture와 Monolithic Architecture이란? (0) 2022.11.26 WAR, JAR 이란? (0) 2022.11.17 정적페이지와 동적페이지란? (0) 2022.11.17 DOM이란? (0) 2022.11.16