정수에는 자리수의 유한 함으로 수의 넘침 현상이 일어나고 , 실수에는 정확한 수를 표현할 수가 없는 경우가 있습니다. 이 부분에 초점을 두겠습니다.
float 형 변수는 다음과 같은 틀의 형태로 저장된다.
예를 들어 10 진수는 12.5 는
*지수부에는 bias 라는 것을 적용해서 지수값에 127 을 더한 후 지수부에 기억한다.
- 먼저 이를 2 진수로 바꾸면 1100.1
- 이를 1.xxx 형태로 바꾼다. 1.1001 * 2^3 ( 이를 정규화..normalization...이라 함)
- 1001 부분을 소수부에 , 3 즉 11 을 소수부에 기억한다.
----확인
#include <stdio.h> int main() { float a; a = 12.5; printf("%x",a); }그런데 %x 는 실수형에서는 작동이 되지 않는가 제대로 된 결과를 볼수가 없어 다음과 같은 코드로 다시 시도.#include <stdio.h> int main() { float *a; a = new float; *a = 12.5; printf("%x",*(int*)a); }위에서 설명한 대로 출력되는 것을 확인 함.(vc 와 gcc 동일)41480000
만약 소수부의 자리수를 4 비트로 사용한다면 소수부가 나타낼 수 있는 것은0.0 과 0.0625 사이에 있는 수는 이 둘 중 하나로 표현될 수 밖에 없습니다. 이 0.0625 를 Epsilon 오차라 합니다.
- 0000 ... 10 진수 0.0
- 0001 ... 10 진수 0.0625
- 0010 ... 10 진수 0.25
- ...
- 1111 ...
그래서 가능하면 소수부가 크면 클수록 더 정확하게 표현할 수가 있으니 정확한 연산을 위해서는 소수부를 3 바이트 쓰는 float 보다는 소수부를 3 + 4 = 7 바이트 사용하는 double 형을 사용하는게 안전합니다. 물론 double 형도 Epsilon 오차가 발생하지만 float 보다는 더 작습니다.
일단 , 두 실수를 비교할 때는 컴퓨터내에서 실수를 표현하는데 유한한 자리와 수체계로 인하여 어느정도의 오차 범위내에서 수를 비교하는게 안전할 듯 합니다.두 실수 a,b 가 있다면
if ( a == b ) ..
보다는if ( fabs( a - b) < DBL_EPSILON ) ....
fabs 두 실수의 절대값 구하는 함수이고 두 수의 차가 double 형의 오차의 한계 DBL_EPSION 보다 작으면으로 가는게 안전한 코딩이 될 것 같습니다. 여기에서 fabs 는 math.h 에 DBL_EPSION 은 float.h 에 정의가 되어 있습니다.
#include <math.h> #include <float.h> int main() { double a,b; ... if( fabs( a - b) < DBL_EPSILON ){ // a 와 b 가 같으면 .... } }
출처:dovelet