반응형

프로그래밍/C,C++

반응형
반응형

때로는 정말 간단한 것인데 까먹는 경우가 있다. 부동소수점의 오차가 그런 것 아닐까?

java나 python 등에서는 발생하는지는 모르겠지만, C와 C++에서는 특히 조심해야 할 부분이다.

실제로 내가 했던 코드의 일부분이다.

위 코드에서 zoom은 float형태이고, 실행하다 보면 zoom += 0.1과 같은 연산을 많이 한다. zoom+=0.1과 같은 연산을 하지 않은 상태에서 비교하면 아무런 문제가 없지만, zoom+=0.1 뿐만 아니라 소수점 연산을 많이 해주게 되다 보면 약간의 오차가 생기게 되는데 이는 프로그램이 작동이 안되는 큰 문제로 다가오게 된다. 소스코드에서 한 글자만 없어도 프로그램 전체가 실행이 안되는 사례가 종종 있다. (여담으로 1996년에 있었던 Ariane5 Tragedy라는 것이 있는데, 16bit 연산만 가능하도록 프로그램을 짰는데 오버플로우가 나면서 우주선이 폭발했다.) 내 프로그램도 마찬가지였다.

Ariane5 Tragedy

 

*문제 원인

 이런 코드가 있다고 치자. a를 0으로 초기화하고, a에 0.1을 10번 더해준다. 그러면 a는 1.0이 되는 것이 정상이다. 

 

출력을 봐보자

정상적으로 1.000000이 나오는 것을 볼 수 있다. 그렇다면 문제가 없는 것일까?

a와 1의 크기를 비교하는 아래 코드를 보자.

간단한 코드지만 간략하게 설명하면, a가 1과 같다면 같다고 출력하고, 크면 크다고, 작으면 작다고 출력하는 코드다. 위에서 a는 1인 것을 확인했는데 놀랍게도 a는 1보다 크다고 나왔다. 

 

왜 이런 현상이 발생하는 걸까?

답은 "오차"다.

 

다시 a를 소수점 아홉번째 자리까지 출력해보자.

 

 

%.9f를 통해 소수점을 아홉번째자리까지 출력하였다.

 

결과는 아래와 같았다.

놀랍게도 답은 1.000000000000000..이 아닌 1.000000119가 나왔다. 그냥 float를 출력하면 소수점 여섯째자리까지만 출력해서 1.000000만 나오는데, 바로 뒤 일곱번재 자리에 오차가 있었다. 

 

*해결방법

 오차를 해결할 수 있는 방법이 있을지는 모르겠지만, 오차를 무시하고 사용하면 된다. 예를 들면, 위에서 0.1이 열 번 더해진 1.000000119를 1과 같은지 알아보고 싶다면, "a-ABS(a-1) == 1fabsf(a - 1.0f) <= FLT_EPSILON"과 같이 작성해서 같은지 비교해볼 수 있을 것이다.

 

정상적으로 같다고 출력된다.

반응형

+ Recent posts