Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is floating point overflow handled in iostreams

Tags:

c++

iostream

g++

I have some very simple code:

#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;
}

When I compile this code with g++ 4.1.2 and run it on Redhat 5.10 (same compiler), I get the output:

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

When I execute the same binary on Redhat Linux 6.5 (compiler 4.4.7), I get

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

What is the expected behavior? Underflow is succeeeding on 4.4.7 but failing on 4.1.2. Overflow fails (but still changes the value) on 4.4.7 and fails without changing anything on 4.1.2.

Is the behavior undefined or simply incorrect on one or the other?

like image 206
Ronald Van Iwaarden Avatar asked Sep 12 '14 14:09

Ronald Van Iwaarden


People also ask

How do you handle floating point exception?

Before you can trap floating-point (FP) exceptions using structured exception handling, you must call the _controlfp_s C run-time library function to turn on all possible FP exceptions. To trap only particular exceptions, use only the flags that correspond to the exceptions to be trapped.

What happens when a float overflows?

In general, a floating point overflow occurs whenever the value being assigned to a variable is larger than the maximum possible value for that variable. Floating point overflows in MODFLOW can be a symptom of a problem with the model.

How is integer overflow different from floating point overflow?

"When integer overflow occurs the value of the offending variable will “wrap around” to negative val-ues, producing erroneous results. When floating-point overflow occurs, the value of the offending variable will be set to the constant inf representing infinity."


1 Answers

According to C++11 22.4.2.1.2, the conversion should fail for overflow, but not underflow. In the case of overflow, it should still give a value of the largest representable value as well as setting failbit.

So your more recent compiler has the correct modern behaviour.

However, both of your ancient compilers predate C++11 by many years. In earlier standards, the conversion was specified to give an error if scanf would; and not to give a value in case of error. Turning to the C standard, scanf defers to strtod, which in turn specifies an error on overflow; but whether there's an error on underflow is implementation-defined.

So your older compiler is consistent with historical behaviour.

like image 182
Mike Seymour Avatar answered Oct 08 '22 15:10

Mike Seymour