// Simple test program to demonstrate a failure to 'loopback' or 'round trip' // double to and from a stream, here std::stringstream // but possibly, even probably, ALL streams, including cout and cin? // This shows a single example, but some further tests with random values // have shown that most failures occur in a narrow range, about 0.0001 to 0.005. // About one value in three is a single bit 'wrong' in these ranges. // Although the C++ Standard is not quite explicit whether this should // return exactly the same value, it is extremely desirable. // For example, Boost lexical_cast and Boost.serialization use the process below. // If one serializes and restores, then checks will (have!) revealed this difference. // Much more seriously, repeated serialization and de-serialization will add // one bit to some values on each trip causing the value to drift, and // an exquisitely difficult/impossible debugging task. // An exhaustive test using ALL float values, the results are exact. // For double, this is not possible in a useful time ;-) // Copyright Paul A. Bristow 1998-2006. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // pbristow@hetp.u-net.com #include using std::cout; using std::endl; #include using std::stringstream; #include int main () { double output_value = 0.00010000433948393407; cout.precision(17); // max_digits10 for double. stringstream stream; stream.precision(17); // max_digits10 for double. stream << output_value; // write out. double read_value; stream >> read_value; // read back. assert(read_value == output_value); // in debug mode only (of course!). if (read_value != output_value) // so can test in release mode too. { cout << "output_value " << output_value << " != read_value " << read_value << endl; } } // main /* Both compiled with VS 8.0, including a post-build autorun. ------ Build started: Project: loopback2, Configuration: Debug Win32 ------ Compiling... loopback2.cpp Linking... Embedding manifest... Autorun "j:\Cpp\Misc\debug\loopback2.exe" Assertion failed: read_value == output_value, file j:\cpp\misc\loopback2\loopback2.cpp, line 42 Project : error PRJ0019: A tool returned an error code from "Autorun "j:\Cpp\Misc\debug\loopback2.exe" " Build Time 0:06 Build log was saved at "file://j:\Cpp\Misc\loopback2\Debug\BuildLog.htm" loopback2 - 1 error(s), 0 warning(s) ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== ------ Build started: Project: loopback2, Configuration: Release Win32 ------ Compiling... loopback2.cpp Linking... Generating code Finished generating code Embedding manifest... Autorun "j:\Cpp\Misc\release\loopback2.exe" output_value 0.00010000433948393407 != read_value 0.00010000433948393406 Build Time 0:02 Build log was saved at "file://j:\Cpp\Misc\loopback2\Release\BuildLog.htm" loopback2 - 0 error(s), 0 warning(s) ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== */