如何在iostream中处理浮点溢出

时间:2014-09-12 14:32:47

标签: c++ g++ iostream

我有一些非常简单的代码:

#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没有改变任何内容的情况下失败。

行为是否未定义或仅在一个或另一个上不正确?

1 个答案:

答案 0 :(得分:3)

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

因此,您最近的编译器具有正确的现代行为。

然而,你的两个古代编译器都早于C ++ 11多年。在早期标准中,指定转换为scanf时会出错;并且在出错时不给出值。转到C标准,scanf遵循strtod,后者又指定溢出错误;但是下溢是否存在错误是实现定义的。

因此,您的旧编译器与历史行为一致。