2011-08-08 3 views
2

NaN을 Windows CRT string에서 float 함수로 가져 오는 방법이 있습니까? MSVCRT strtod/sscanf/atof 함수에서 NaN을 가져올 수 없습니다.


이유 : 내가 어떤 정보 손실 C의 IEEE floatstring 변환기를 쓰고 있어요 (strtod, sscanf을하거나 원래 float을 반환 atof)는 둥근 모드가 변경되지 않습니다 제공.

저는 MinGW 또는 Visual C++로되어 있으므로 이러한 호출은 MSVC++ 런타임으로 이동합니다. 문제는 어떤 특별한 값 (예 : "Inf" 또는 "NaN")을 파싱 할 수 없다는 것입니다. Inffloat에 맞지 않는 값 (예 : "1e999")을 파싱 한 후에 반환됩니다. 입력이 구문 분석 또는 언더 플로우가 발생 할 수없는 경우 오버 플로우가 발생 0한다면

/* Return the shortest string representation of a float with a successful scanf round-trip. 
    * Guaranteed to fit in 13 chars (including the final '\0'). 
    */ 
    char* ftoa(char* res, float f) { 
    float r = 0; 
    int i, j, len, e = floor(log10(f)) + 1; 
    char fmt[8]; 
    union { float f; int32_t i; } u = { f } ; 

    if (f > FLT_MAX) { sprintf(res, "1e999"); return res; } 
    if (f < -FLT_MAX) { sprintf(res, "-1e999"); return res; } 

    if ((u.i & 0x7F800000) == 0x7F800000) { // NaN 
     sprintf(res, u.i == 0x7FC00000 ? "%sNaN" : "%sNaN%d", u.i<0 ? "-" : "", u.i & 0x7FFFFF); 
     return res; 
    } 

    // compute the shortest string without exponent ("123000", "0.15") 
    if (!f || e>-4 && e<10) { 
     for (i=0; i<=10; i++) { 
      sprintf(fmt, "%%.%df", i); 
      sprintf(res, fmt, f); 
      sscanf(res, "%f", &r); if (r==f) break; 
     } 
    } 
    if (r==f) len = strlen(res); 
    else len = 1e9; 

    if (!f) return res; // handle 0 and -0 

    // compute the shortest string with exponent ("123e3", "15e-2") 
    for (i=0; i<9; i++) { 
     sprintf(res, "%.0fe%d", f * pow(10,-e), e); sscanf(res, "%f", &r); if (r==f) break; 
     j = strlen(res); if (j >= lenF) break; 
     while (res[j] != 'e') j--; 
     res[j-1]--; sscanf(res, "%f", &r); if (r==f) break; // try +-1 
     res[j-1]+=2; sscanf(res, "%f", &r); if (r==f) break; 
     e--; 
    } 
    if (len <= strlen(res)) sprintf(res, fmt, f); 
    return res; 
    } 
+0

원래 번호를 다시 비트 단위로 사용해야하거나 페이로드 비트를 보존 할 필요가 없습니다. 둘 다 사실 일 수 없다. 또한 인코더/디코더 쌍의이 기능을 무손실이 아닌 "라운드 트립 (round-tripping)"이라고합니다. * 무손실 (Lossless) *은 인코딩 자체를 나타내는 것이지, 그것을 생성하는 함수가 아닙니다. –

+0

@BenVoigt 의견을 보내 주셔서 감사합니다. 실제로 페이로드 비트를 보존해야한다고 밝혀졌습니다. –

+0

'boost :: math :: nonfinite_num_get/put'을 사용하는 솔루션 : http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/fp_facets/intro.html –

답변

1

번호 그들은 HUGE_VAL 돌아갑니다.

+0

감사합니다. 그것이 맞다면 그것은 나쁜 소식입니다. 나는 NaN을 테스트하는'strtod' 주위에 래퍼가 필요하다고 생각합니다. –

+0

맞습니다. http://msdn.microsoft.com/en-us/library/kxsfc1ab.aspx –

관련 문제