【问题标题】:Can't get a NaN from the MSVCRT strtod/sscanf/atof functions无法从 MSVCRT strtod/sscanf/atof 函数中获取 NaN
【发布时间】:2011-10-22 17:23:07
【问题描述】:

有没有办法从 Windows CRT stringfloat 函数中获取 NaNs?


原因:我正在用 C 语言编写一个 IEEE floatstring 转换器,没有信息丢失(strtodsscanfatof 返回原始 float ) 前提是舍入模式不变。

我在 MinGW 或 Visual C++ 下,所以这些调用转到 MSVC++ 运行时。问题是我无法让它解析任何特殊值(如"Inf""NaN")。 Inf 可以(解析一个不适合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;
  }

【问题讨论】:

  • 要么您需要原始数字逐位返回,要么您不需要保留有效负载位。两者都不可能是真的。此外,编码器/解码器对的这一特性称为“往返”,而不是无损。 无损指的是编码本身,而不是创建它的函数。
  • @BenVoigt 感谢您的输入,重新制定。实际上,我需要保留有效载荷位。
  • 使用boost::math::nonfinite_num_get/put的解决方案:boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/…

标签: c++ floating-point msvcrt scanf strtod


【解决方案1】:

没有。如果发生上溢,则返回 HUGE_VAL,如果无法解析输入或发生下溢,则返回 0。

【讨论】:

  • 谢谢。如果这是正确的,那就是坏消息。我想我需要一个围绕 strtod 的包装器来测试 NaN。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-03
  • 2017-08-02
  • 2018-05-26
相关资源
最近更新 更多