상수 머신 엡실론값?
아래는 실수를 문자열로 변환해주는 함수 인데 허점이 있는거 같습니다.
잘 작동할도 있고 오작동할때도 있는데
오작동 하면
30.8을 변환하면 30.7999999 가 되버립니다.
원인을 파악하기 위해 로그를 남기던중
do while부분에서 문제가 발생하기 시작하는것을 발견했습니다.
상수인 FLT_EPSILON값이 정상작동할때는 0.00000으로 출력되고
오작동시에는 nan으로 출력되며 do while문을 과도하게 많이 돌게 됩니다.
왜 이런현상이 나타나며 해결방법은 무었일까요?
size_t utils_floatToText(double data,
uint8_t * string,
size_t length)
{
size_t intLength;
size_t decLength;
int64_t intPart;
double decPart;
if (data <= (double)INT64_MIN || data >= (double)INT64_MAX) return 0;
intPart = (int64_t)data;
decPart = data - intPart;
if (decPart < 0)
{
decPart = 1 - decPart;
}
else
{
decPart = 1 + decPart;
}
if (decPart <= 1 + FLT_EPSILON)
{
decPart = 0;
}
if (intPart == 0 && data < 0)
{
// deal with numbers between -1 and 0
if (length < 4) return 0; // "-0.n"
string[0] = '-';
string[1] = '0';
intLength = 2;
}
else
{
intLength = utils_intToText(intPart, string, length);
if (intLength == 0) return 0;
}
decLength = 0;
if (decPart >= FLT_EPSILON)
{
int i;
double noiseFloor;
if (intLength >= length - 1) return 0;
i = 0;
noiseFloor = FLT_EPSILON;
do
{
decPart *= 10;
noiseFloor *= 10;
fprintf(stderr,"decPart = %f , noiseFloor = %f \n",decPart,string + intLength);
i++;
} while (decPart - (int64_t)decPart > noiseFloor);
decLength = utils_intToText(decPart, string + intLength, length - intLength);
if (decLength <= 1) return 0;
// replace the leading 1 with a dot
string[intLength] = '.';
}
fprintf(stderr,"decPart = %f , convert = %s \n",decPart,string + intLength);
return intLength + decLength;
}아래는 실행 로그 입니다.
dataP->value.asFloat : 31.500000
dataP->type : 7
lwm2m_data_serialize
floatttttttttt
decPart = 15.000000 , noiseFloor = 0.000000 <--- 정상작동시의 do while 문
decPart = 15.000000 , convert = .5�r
utils_float64ToPlainText 31.500000 31.5%
report change!
expernet data
report change!
dataP->value.asFloat : 31.700000
dataP->type : 7
lwm2m_data_serialize
floatttttttttt
decPart = 17.000000 , noiseFloor = nan <--------정상작동시 0.00000으로 출력되던 상수가 nan으로 출력되며 do while문을 과도하게 많이 돌며 오작동
decPart = 170.000000 , noiseFloor = nan
decPart = 1700.000000 , noiseFloor = nan
decPart = 17000.000000 , noiseFloor = nan
decPart = 170000.000000 , noiseFloor = nan
decPart = 1700000.000000 , noiseFloor = nan
decPart = 17000000.000000 , noiseFloor = nan
decPart = 17000000.000000 , convert = .6999999
utils_float64ToPlainText 31.700000 31.6999999 �


댓글 달기