2014-09-12 50 views
8

我有一些非常简单的代码来处理:如何浮点溢出输入输出流

#include <iostream> 
#include <sstream> 
using namespace std; 

int main() 
{ 
    stringstream is("1.0 2.0 1e-500 1e500 12.0"); 
    double d = {17.0, 17.0, 17.0, 17.0, 17.0}; 

    for (int i=0; i < 5; ++i) 
    { 
    if (is >> d[i]) 
    { 
     cout<<"Conversion succeeded"<<endl; 
    } 
    else 
    { 
     cout<<"Conversion failed"<<endl; 
     is.clear(); 
    } 
    } 
    for (int i=0; i < 5; ++i) cout<<d[i]<<endl; 
} 

当我编译这段代码G ++ 4.1.2在Redhat 5.10(相同的编译器)运行它,我得到的输出:

Conversion succeeded 
Conversion succeeded 
Conversion failed 
Conversion failed 
Conversion succeeded 
1 
2 
0 
17 
17 
12 

当我在Redhat Linux上执行相同的二进制6.5(编译器4.4.7),我得到

Conversion succeeded 
Conversion succeeded 
Conversion succeeded 
Conversion failed 
Conversion succeeded 
1 
2 
0 
1.79769e+308 
12 

什么是电子预期行为?下溢在4.4.7上成功,但在4.1.2上失败。溢出失败(但仍然改变值)在4.4.7上,并且在没有改变4.1.2上的任何内容的情况下失败。

行为是未定义的还是简单地不正确?

+0

好问题。 '>>'是间接的(通过'num_get'),按照'strtold'的规则来定义,对于后者,明确地说未规定下溢是否被视为错误条件。但是,下溢不会被视为“num_get”的错误条件之一。我不确定这是否意味着它没有指定,或者定义为成功返回0。 – hvd 2014-09-12 14:52:59

回答

3

根据C++ 11 22.4.2.1.2,转换失败的溢出,但不下溢。在溢出的情况下,它应该仍然给出最大的可表示值以及设置failbit

所以你最近的编译器有正确的现代行为。

但是,您的古代编译器早在C++ 11之前就已经存在多年。在较早的标准中,如果scanf会将转换指定为给出错误;而不是在错误的情况下给出价值。转向C标准,scanf按照strtod,这反过来指定溢出错误;但下溢时是否有错误是由实现定义的。

所以你的旧编译器与历史行为一致。