Floating point(실수) 계산은 때때로 문제가 되며, 신비스럽게 보이기도 합니다. 게다가 C 언어는 원래 floating point를 주로 쓸 목적이 아니었기 때문에 더욱 문제가 됩니다.
<math.h>
를 포함시켰는지 검사해 보고, 함수들이
double을 리턴하도록 선언되었는지 체크해보기 바랍니다.
(atof() 함수는 <stdlib.h>
에 선언되어 있음을 주의하기
바랍니다.) 덧붙여 질문
14.3도 참고하시기 바랍니다.
<math.h>
를 포함시켰는데도
컴파일러는 “undefined: sin”이라는 컴파일 에러를 출력합니다.
문제가 간단하지 않겠지만, 디지털 컴퓨터에서 실수 처리는 정확하지 않을 수도 있다는 것을 알아두셔야 합니다. 언더플로우(underflow)가 일어날 수도 있으며, 오차가 점점 누적될 수도 있습니다.
따라서 실수 연산이 정확하지 않다는 것을 기억하기 바라며, 같은 이유로 두 실수가 같은지 비교하는 것은 좋지 않습니다. (Don't throw haphazard “fuzz factors” in, either; 질문 14.5를 참고하기 바랍니다.)
이런 문제는 꼭 C 언어에만 국한된 것이 아니고, 모든 프로그래밍 언어에서 발생할 수 있습니다. 실수에 대한 어떤 부분들은 대개 “프로세서가 어떻게 처리하느냐”에 따라 다릅니다 (덧붙여 질문 11.34도 참고하시기 바랍니다.), 그렇지 않는 경우라면 적절한 기능을 수행할 수 있게 하기 위해 댓가가 큰 에뮬레이션을 사용합니다.
안타깝게도 이 문서는 이런 실수 연산에 대한 단점이나 해결책을 위한 것이 아닙니다. 좋은 수치 프로그래밍에 (numerical programming) 대한 책들이 여러분을 도와줄 겁니다. 아래 참고 문헌에 나온 책들을 보시면 좋습니다.
double a, b; ... if (a == b) /* WRONG */
이렇게 합니다:
#include <math.h> if (fabs(a - b) <= epsilon * fabs(a))... TODO ...
(int)(x + 0.5)단, 이 기법은 음수에는 쓸 수 없습니다. 음수에는 다음과 같은 코드를 써야 할 것입니다:
(int)(x < 0 ? x - 0.5 : x + 0.5)
<math.h>
에 선언되어 있습니다.
크기가 작고 0보다 큰 정수를 곱하는 것이 이 함수를 쓰는 것보다
더 효과적일 수도 있습니다.
<math.h>
에는 매크로 M_PI
가 정의되어
있지 않습니다.
4 * atan(1.0)
으로
계산해야 합니다.
<math.h>
나 <ieee.h>
, <nan.h>
에
선언되어 있을 수 있습니다.) 이런 값들을 다루기 위한 함수들을 제공합니다.
그리고 이런 기능들을 지금 표준화하려고 하고 있답니다.
NaN을 검사하는 가장 거칠고(crude) 간단한 방법은 다음과 같습니다.
#define isnan(x) ((x) != (x))IEEE를 생각하지 않은 컴파일러는 이런 테스트를 최적화 단계에서 없애버릴 수도 있습니다14.1.
[C9X]는 isnan(), fpclassify() 등과 다른 종류 함수들을 제공합니다.
또 하나의 방법은 이 실수를 sprintf()와 같은 루틴을 써서 포맷화시켜 보는 것입니다. 많은 시스템이 이런 경우 “NaN”이나 “Inf”와 같은 문자열을 만들어 줄 겁니다.
Seong-Kook Shin