상수 머신 엡실론값?
아래는 실수를 문자열로 변환해주는 함수 인데 허점이 있는거 같습니다.
잘 작동할도 있고 오작동할때도 있는데
오작동 하면
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 �
댓글 달기