2011-08-08 10 views
2

NaNをWindows CRT stringからfloatに変換する方法はありますか?MSVCRT strtod/sscanf/atof関数からNaNを取得できません


理由:ノー情報損失(strtodsscanfまたはatoffloatを返す)とCでのIEEE floatstringへのコンバータを書いては丸めモードは変更されません提供。

私はMinGWまたはVisual C++の下にあるので、これらの呼び出しはMSVC++ランタイムに移動します。問題は、特別な値(たとえば"Inf"または"NaN"など)を解析することができないということです。 InfはOKです(これはfloatに収まらない値、たとえば"1e999"の値を解析した後に返されます)。

/* 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

元の番号をbit-for-bitにするか、ペイロードビットを保持する必要はありません。どちらも真実ではありません。また、エンコーダ/デコーダのペアのこの機能は、「ラウンドトリップ」と呼ばれ、無損失ではありません。 * 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

入力が解析できないやアンダーフローが発生した場合、オーバーフローが発生すると0になる場合、それらはHUGE_VALを返す号。

+0

ありがとうございます。それが正しいならば、それは悪いニュースです。 NaNをテストする 'strtod'の周りにラッパーが必要になると思います。 –

+0

正しいです。 http://msdn.microsoft.com/en-us/library/kxsfc1ab.aspx –

関連する問題