std :: scientific总是会导致浮点数的标准化科学记数法吗?

时间:2018-05-29 11:50:24

标签: c++ floating-point scientific-notation

科学记数法定义了如何使用符号,数字和指数显示数字,但它并未声明可视化是规范化的。

一个例子: -2.34e-2 (标准化科学记数法)与 -0.234e-1 (科学记数法)相同

我可以依赖以下代码始终产生标准化结果吗? 编辑,除了答案中指出的NAN和INF。

template<typename T>
static std::string toScientificNotation(T number, unsigned significantDigits)
{
    if (significantDigits > 0) {
        significantDigits--;
    }
    std::stringstream ss;
    ss.precision(significantDigits);
    ss << std::scientific << number;
    return ss.str();
}

如果是,请列出C ++文档/标准中的一节,说明它不是平台/实现定义的。由于0的值也有不同的表示,我担心某些非常小的数字(非规范化的?!)可以被不同地显示出来。在我的平台上使用我的编译器,它目前适用于std :: numeric_limits :: min(),denorm_min()。

注意:我使用它来查找数字的数量级而不会弄乱浮点数分析的所有细节。我希望标准库为我做: - )

2 个答案:

答案 0 :(得分:4)

  

我可以依赖以下代码始终产生规范化结果吗?

无法保证,不。更好地说:标准并没有像你希望的那样强有力的保证。

std::scientific仅在以下相关部分引用:

  1. [floatfield.manip]:2

    ios_base& scientific(ios_base& str);  
    
         

    效果:致电str.setf(ios_­base​::​scientific, ios_­base​::​floatfield)   返回str

  2. Table 101 — fmtflags effects

    | Element    | Effect(s) if set                                       |
    | ...        | ...                                                    |
    | scientific | generates floating-point output in scientific notation |
    | ...        | ...                                                    |
    

答案 1 :(得分:2)

是的,除了零,无穷大和NaN。

C ++标准是指格式化的C标准,需要标准化的科学记数法。

  • [floatfield.manip]/2

    ios_base& scientific(ios_base& str);
    
         

    效果:致电str.setf(ios_­base​::​scientific, ios_­base​::​floatfield)

         

    返回:str

  • [ostream.inserters.arithmetic]/1(部分)

    operator<<(float val);
    operator<<(double val);
    operator<<(long double val);
    
         

    效果:num_­get<>num_­put<>处理依赖于区域设置的数字格式和解析。这些插入器函数使用嵌入式locale值来执行数字格式设置。如果val的类型为...,doublelong double,...,则格式转换就像执行以下代码片段一样:

    bool failed = use_facet<
      num_put<charT, ostreambuf_iterator<charT, traits>>
        >(getloc()).put(*this, *this, fill(), val).failed();
    
         

    val类型为float时,格式转换就像执行以下代码片段一样:

    bool failed = use_facet<
      num_put<charT, ostreambuf_iterator<charT, traits>>
        >(getloc()).put(*this, *this, fill(),
          static_cast<double>(val)).failed();
    
  • [facet.num.put.virtuals]/1:5.1(部分)

      
        
    • 第1阶段:

           

      第1阶段的第一个操作是确定转换说明符。描述此确定的表使用以下局部变量

      fmtflags flags = str.flags();
      fmtflags floatfield = (flags & (ios_base::floatfield));
      
           

      对于从浮点类型的转换,该函数确定浮点转换说明符,如表70所示。

           

      表70 - 浮点转换

      | State                                            | stdio equivalent |
      | ------------------------------------------------ | ---------------- |
      | floatfield == ios_­base​::​scientific && !uppercase | %e               |
      | floatfield == ios_­base​::​scientific               | %E               |
      
           

      第1阶段结束时的陈述包含char,这些将通过调用printf(s, val) 打印,其中s是转化上面确定的说明符。

    •   
  • C11 n1570 [7.21.6.1]:8.4

      
        
    • <强>电子,<强>电子

           

      表示浮点数的double参数在。中转换   style [ - ] d.ddd e ±dd 哪里有一位数字(如果是   参数非零)小数点前的字符和数字   等于精度后的数字;如果精度丢失,则取6;如果精度为零且未指定标志,则不包含小数点   角色出现。该值四舍五入到适当的位数。 E 转换说明符生成的数字 E 而不是 e   介绍指数。指数始终包含至少两位数,   并且只需要表示指数所需的数字。 如果   值为零,指数为零。

           

      表示无穷大或NaN的double参数将以 f F 转换说明符的样式进行转换。

    •