부동 소수점 숫자의 정밀도가 떨어지는 이유
일반적으로 부동 소수점 10진수 값에는 정확히 일치하는 이진 표현이 없습니다. 이는 CPU가 부동 소수점 데이터를 표현하는 방식의 부작용입니다. 해당 이유로 일부 자릿수가 손실될 수 있으며 일부 부동 소수점 연산으로 인해 예기치 않은 결과가 발생할 수 있습니다.
이 동작은 다음 중 하나에 해당하는 결과입니다.
10진수의 이진 표현은 정확하지 않을 수 있습니다.
사용된 숫자(예: float과 double 혼합) 간에 형식이 일치하지 않습니다.
프로그래머는 대부분 이 동작을 해결하는 데 필요한 값보다 크거나 작도록 하거나 전체 자릿수를 유지하는 BCD(이진 코딩된 10진수) 라이브러리를 가져와서 사용합니다.
부동 소수점 값의 이진 표현은 부동 소수점 계산의 전체 자릿수 및 정확도에 영향을 줍니다. Microsoft Visual C++는 IEEE 부동 소수점 형식을 사용합니다.
예시
// Floating-point_number_precision.c
// Compile options needed: none. Value of c is printed with a decimal
// point precision of 10 and 6 (printf rounded value by default) to
// show the difference
#include <stdio.h>
#define EPSILON 0.0001 // Define your own tolerance
#define FLOAT_EQ(x,v) (((v - EPSILON) < x) && (x <( v + EPSILON)))
int main() {
float a, b, c;
a = 1.345f;
b = 1.123f;
c = a + b;
// if (FLOAT_EQ(c, 2.468)) // Remove comment for correct result
if (c == 2.468) // Comment this line for correct result
printf_s("They are equal.\n");
else
printf_s("They are not equal! The value of c is %13.10f "
"or %f",c,c);
}
They are not equal! The value of c is 2.4679999352 or 2.468000
설명
EPSILON의 경우 float에 대해 1.192092896e-07F로 정의된 상수 FLT_EPSILON 또는 double에 대해 2.2204460492503131e-016으로 정의된 DBL_EPSILON을 사용할 수 있습니다. 관련 상수에는 float.h를 포함해야 합니다. 해당 상수는 x + 1.0이 1.0과 같지 않은 가장 작은 양수 x로 정의됩니다. 매우 작은 수이므로 매우 큰 숫자를 포함하는 계산의 경우 사용자 정의 오차를 사용해야 합니다.