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?
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.
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.
"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."
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With