S
soeren
Hello,
two days ago I stumbled across a very strange problem that came up when
we were printing tiny double numbers as strings and trying to read them
on another place. This is part of an object serialisation framework
that cannot be done in binary format currently, so please no comments
about this ,-))
It took quite some time to shrink down the problem but it looks like
that C++ does not behave well in regards to very tiny numbers.
The <limits> header of the STL defines various templates that should
return amonst other things the tiniest negative double number that C++
can handle. The line
cout << numeric_limits<double>::min() << endl;
returns "2.22507e-308". So I would expect that every number closer to
zero (but still negative) would be treated as zero?
Please have a look at the following code snippet (insert it into a
"main" to run it on your compiler):
ostringstream output;
istringstream input;
// Regarding the limits this should assign zero to foobar, but it
doesn't look like that ?!?
double foobar = -2.345e-315;
// Simply put three numbers on the stream
output << 10 << " ";
output << 2.12345 << " ";
output << foobar << " ";
output << 10 << endl;
// Print out the resulting stream, you should see the above three
numbers
cout << output.str() << endl;
// Generate input stream from the output stream
input.str(output.str());
int int1=0, int2=0;
double double1=0, double2=0;
// For every read action print out the stream state
input >> int1;
cout << input.good() << endl;
input >> double1;
cout << input.good() << endl;
// Here comes the read of the "wrong" double
input >> double2;
cout << input.good() << endl;
input >> int2;
cout << input.good() << endl << endl;
// Now print out the numbers from the stream
cout << int1 << endl;
cout << double1 << endl;
cout << double2 << endl;
cout << int2 << endl;
Although I'm doing this example with three numbers only the 3rd number
is of interest as this number is a double value that should be zero
after the assignment from my understanding.
Various things come up when running the code that I cannot explain
currently:
1) The assignment obviously does not assign zero. Proof: Printing the
resulting stream yields "-2.345e-315" as the third number (checked on
..NET 2003 C++ and g++ 4.0/Linux). Why that?
2) The number is printed to the stream as "-2.345e-315". But regarding
<limits> this number should impossible to handle?
3) The accompanying read action results in different behavious
.NET 2003: input.good() toggles to "false" after read, the read
number "double2" is not read, subsequent reads fail.
g++ 4.0/Linux: The number is read, the stream state is "true",
subsequent numbers are read.
Why does this code work on g++? This should not run as the numeric
limit produces exactly the same number as with .NET2003
#3 currently produces the biggest headaches as in our current framework
this very tiny numbers are produces on linux servers but must be read
on windows clients. Following the above tests this cannot work.
So beside the basic question "What is the real limit of a double number
and why does this not work in c++?" there seems to be some platform
dependante implementations; what is the reason for this?
Thanks a lot for shedding some light in this issue,
Soeren Gerlach
two days ago I stumbled across a very strange problem that came up when
we were printing tiny double numbers as strings and trying to read them
on another place. This is part of an object serialisation framework
that cannot be done in binary format currently, so please no comments
about this ,-))
It took quite some time to shrink down the problem but it looks like
that C++ does not behave well in regards to very tiny numbers.
The <limits> header of the STL defines various templates that should
return amonst other things the tiniest negative double number that C++
can handle. The line
cout << numeric_limits<double>::min() << endl;
returns "2.22507e-308". So I would expect that every number closer to
zero (but still negative) would be treated as zero?
Please have a look at the following code snippet (insert it into a
"main" to run it on your compiler):
ostringstream output;
istringstream input;
// Regarding the limits this should assign zero to foobar, but it
doesn't look like that ?!?
double foobar = -2.345e-315;
// Simply put three numbers on the stream
output << 10 << " ";
output << 2.12345 << " ";
output << foobar << " ";
output << 10 << endl;
// Print out the resulting stream, you should see the above three
numbers
cout << output.str() << endl;
// Generate input stream from the output stream
input.str(output.str());
int int1=0, int2=0;
double double1=0, double2=0;
// For every read action print out the stream state
input >> int1;
cout << input.good() << endl;
input >> double1;
cout << input.good() << endl;
// Here comes the read of the "wrong" double
input >> double2;
cout << input.good() << endl;
input >> int2;
cout << input.good() << endl << endl;
// Now print out the numbers from the stream
cout << int1 << endl;
cout << double1 << endl;
cout << double2 << endl;
cout << int2 << endl;
Although I'm doing this example with three numbers only the 3rd number
is of interest as this number is a double value that should be zero
after the assignment from my understanding.
Various things come up when running the code that I cannot explain
currently:
1) The assignment obviously does not assign zero. Proof: Printing the
resulting stream yields "-2.345e-315" as the third number (checked on
..NET 2003 C++ and g++ 4.0/Linux). Why that?
2) The number is printed to the stream as "-2.345e-315". But regarding
<limits> this number should impossible to handle?
3) The accompanying read action results in different behavious
.NET 2003: input.good() toggles to "false" after read, the read
number "double2" is not read, subsequent reads fail.
g++ 4.0/Linux: The number is read, the stream state is "true",
subsequent numbers are read.
Why does this code work on g++? This should not run as the numeric
limit produces exactly the same number as with .NET2003
#3 currently produces the biggest headaches as in our current framework
this very tiny numbers are produces on linux servers but must be read
on windows clients. Following the above tests this cannot work.
So beside the basic question "What is the real limit of a double number
and why does this not work in c++?" there seems to be some platform
dependante implementations; what is the reason for this?
Thanks a lot for shedding some light in this issue,
Soeren Gerlach