提问者:小点点

std::科学总是导致浮点数的标准化科学符号吗?


科学符号定义了如何使用符号、数字和指数显示数字,但它没有说明可视化是标准化的。

举个例子:-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个答案

匿名用户

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

没有保证,没有。更好的说法是:标准没有像你希望的那样提供强有力的保证。

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

>

  • [浮点字段. man ip]:2

    ios_base& scientific(ios_base& str);  
    

    效果:调用str. setf(ios_base::科学,ios_base::floatfield)

    表101-fmt标志效果

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

  • 匿名用户

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

    C标准是指格式化的C标准,它需要标准化的科学符号。

    >

  • [浮点字段. man ip]/2

    ios_base& scientific(ios_base& str);
    

    效果:调用str. setf(ios_base::科学,ios_base::floatfield)

    返回:str

    [ostream.插入器.算术]/1(部分)

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

    效果:num_获得的类

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

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

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

    [facet. num.put.虚拟化]/1:5.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

    >

  • e, E

    表示浮点数的double参数以样式[−]d. ddde±dd转换,其中小数点字符前有一位数字(如果参数非零,则为非零),小数点字符后的位数等于精度;如果缺少精度,则取为6;如果精度为零且未指定#标志,则不出现小数点字符。该值四舍五入到适当的位数。E转换说明符生成一个带有E的数字,而不是引入指数的e。指数始终包含至少两位数字,并且仅根据需要更多的数字来表示指数。如果值为零,则指数为零。

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