상수 머신 엡실론값?

unuseid의 이미지

아래는 실수를 문자열로 변환해주는 함수 인데 허점이 있는거 같습니다.

잘 작동할도 있고 오작동할때도 있는데
오작동 하면
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 �

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.