解析libc ++和glibc中的双精度时不一致的字符串流行为

Hor*_*tor 5 c++ double parsing stringstream

使用gccclang编译以下示例时...

#include <sstream>
#include <iostream>

int main() {
    double val;
    std::stringstream ss("6.93758e-310");
    ss >> val;

    std::cout << "fail: " << ss.fail() << std::endl
}

Run Code Online (Sandbox Code Playgroud)

......我得到不同的行为:

  1. 使用gcc,流的failbit ss.fail()未设置,而
  2. 对于铿锵它是设定的

可能需要注意的是,在这两种情况下,errno都设置为ERANGE.

另外,在本地我得到了与clang和gcc相同的行为,除非我明确地使用libc ++和clang(-stdlib=libc++)而不是glibc.

我不确定正确的行为是什么,但我觉得它应该是一致的.

eer*_*ika 1

输入流提取运算符的行为指定如下:

\n\n
\n

[istream.formatted.arithmetic] 与插入器的情况一样,这些提取器依赖于 locale\xe2\x80\x99s num_get<>([locale.num.get]) 对象\n 来执行对输入流数据的解析。这些提取器的行为类似于格式化输入函数(如 [istream.formatted.reqmts] 中所述)。构造哨兵对象后,将发生转换,就像通过以下代码片段执行的一样:

\n\n
using numget = num_get<charT, istreambuf_iterator<charT, traits>>;\niostate err = iostate::goodbit;\nuse_facet<numget>(loc).get(*this, 0, *this, err, val);\nsetstate(err);\n
Run Code Online (Sandbox Code Playgroud)\n\n

在上面的片段中,loc 代表 basic_ios 类的私有成员。

\n
\n\n

[facet.num.get.virtuals] 有点冗长,但相关部分是:

\n\n
\n

对于双精度值,函数 strtod.

\n\n

...如果该字段表示的值超出了可表示值的范围,则 ios_base::failbit\n 被分配给 err。

\n
\n\n

strtod没有在C++标准中指定,而是在C标准中指定。相关位:

\n\n
\n

7.20.1.3 strtod、strtof 和 strtold 函数

\n\n

\xc2\xa710 如果结果下溢(7.12.1),函数返回一个值,其大小不大于返回类型中最小的标准化正数;errno 是否获取值 ERANGE 是实现定义的。

\n
\n\n

参考规则:

\n\n
\n

7.12.1 错误情况的处理

\n\n

\xc2\xa75 如果数学结果的量级太小,以至于无法在指定类型的对象中表示数学结果(没有异常舍入误差),则结果下溢。204)如果结果下溢,则函数返回一个实现定义的值,其大小不大于指定类型中的最小标准化正数;如果整数表达式 math_errhandling & MATH_ERRNO 不为零,则 errno 是否获取值 ERANGE 是实现定义的;如果整数表达式 math_errhandling & MATH_ERREXCEPT 不为零,则是否引发 \xe2\x80\x98\xe2\x80\x98underflow\xe2\x80\x99\xe2\x80\x99 浮点异常是实现定义的

\n\n

204)这里的术语下溢旨在涵盖IEC 60559中的\xe2\x80\x98\xe2\x80\x98渐进下溢\xe2\x80\x99\xe2\x80\x99以及\xe2\x80\x98\xe2\ x80\x98清零\xe2\x80\x99\xe2\x80\x99下溢。

\n
\n\n
\n\n

尽管 C++ 没有指定浮点运算的表示方式,但您的系统可能使用 IEEE-754 (IEC 60559)。

\n\n

IEEE-754 将下溢指定为:

\n\n
\n

7.5.0(简化)

\n\n

当检测到微小的非零结果时,应发出下溢异常信号。这应该是当计算出的非零结果就好像指数范围和精度都无界时将严格位于 \xc2\xb1b emin之间之间。

\n
\n\n

其中 \xc2\xb1b emin是正法线或负法线是最接近零的它还说:

\n\n
\n

实施者应选择如何检测微小

\n
\n\n
\n\n

所以,回答你的说法:

\n\n
\n

我觉得它应该是一致的。

\n
\n\n

那就太好了,但是下溢的大部分行为都被指定为实现定义的。

\n\n

坦率地说,输入流 API 受到限制,因为在检测到下溢的情况下,它不提供对舍入值的保证访问,也不提供区分下溢故障和其他故障的方法。

\n