[serialization]Double rounding bug?

Hello, I found that for some small double value, serialization change last few digits.(it look like some rounding bug) Below is one example (I have more :) usually it is a number 0.00... or 0.00 with 19-20 digits after dot): -0.0070850229047457131 - double value -0.007085022904745714 - double value after save/read from xml file On my computer I have always assert in function DoubleTest(). Boost: version 1.39/boost_serialization-vc90-mt-gd-1_39.dll Compiler: VS2008 Could you verify below code on your computer (call DoubleTest())? Is it bug? Sample code: #pragma warning( push ) #pragma warning( disable : 4512 ) #include <boost/archive/xml_iarchive.hpp> #pragma warning( pop ) #include <boost/archive/xml_oarchive.hpp> #include <boost/serialization/vector.hpp> #include <boost/bind.hpp> #include <fstream> #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/serialization/vector.hpp> void LoadDoubleValue(DoubleValue& doubleValue, const char* fileName) { std::ifstream ifs(fileName); assert(ifs.good()); boost::archive:: xml_iarchive ia(ifs); ia >> BOOST_SERIALIZATION_NVP(doubleValue); } void SaveDoubleValue(DoubleValue& doubleValue, const char* fileName) { std::ofstream ofs(fileName); assert(ofs.good()); boost::archive::xml_oarchive oa(ofs); oa << BOOST_SERIALIZATION_NVP(doubleValue); } void DoubleTest() { DoubleValue doubleValue1; doubleValue1.m_value = -0.0070850229047457131; SaveDoubleValue(doubleValue1, "DoubleValue.xml"); DoubleValue doubleValue2; LoadDoubleValue(doubleValue2, "DoubleValue.xml"); //but from file is read -0.007085022904745714 assert(doubleValue1.m_value==doubleValue2.m_value); } Best regards, Mariusz

On Thursday 01 October 2009 21:09:00 Mariusz Kwiczala wrote:
DoubleValue doubleValue1; doubleValue1.m_value = -0.0070850229047457131; SaveDoubleValue(doubleValue1, "DoubleValue.xml");
DoubleValue doubleValue2; LoadDoubleValue(doubleValue2, "DoubleValue.xml"); //but from file is read -0.007085022904745714 assert(doubleValue1.m_value==doubleValue2.m_value);
That value would require between 50 and 60 bits of precision, provided its representation is actually possible in a binary floating point number. Typical double-precision floating point numbers have a fraction of 52 bits, so the changes you are reporting are actually to be expected. FYI: The estimate above is that three decimal digits (0-999) are roughly equivalent to ten binary digits (aka bits, decimal 0-1024). You also mention that the difference occurs to numbers with 19-20 digits behind the dot, but that is irrelevant. The important part is the number of significant digits, i.e. the number of digits that are required for the digits without leading and trailing zeroes regardless of whether they are before or after the dot. See also: http://www.validlab.com/goldberg/paper.pdf Note that this would have been better suited to the users' not the developers' mailinglist. Uli

DoubleValue doubleValue1; doubleValue1.m_value = -0.0070850229047457131; SaveDoubleValue(doubleValue1, "DoubleValue.xml");
DoubleValue doubleValue2; LoadDoubleValue(doubleValue2, "DoubleValue.xml"); //but from file is read -0.007085022904745714 assert(doubleValue1.m_value==doubleValue2.m_value);
That value would require between 50 and 60 bits of precision, provided its representation is actually possible in a binary floating point number. Typical double-precision floating point numbers have a fraction of 52 bits, so the changes you are reporting are actually to be expected.
I don't believe that's true: ideally the two values should have the same binary representation. In this case the relative difference between the two values is 1.6e-17 or about 1eps: so my guess is they differ in the last significant bit - that's not a double rounding issue, or shouldn't be. However, I suspect this to be an MSVC issue - there are some numbers that MSVC's IOStreams library can't "round trip serialize" - Robert does Boost.Serialization rely on iostreams internally in this case? I'm cc'ing Paul Bristow on this one, because I know he investigated this issue a while back. HTH, John.
participants (3)
-
John Maddock
-
Mariusz Kwiczala
-
Ulrich Eckhardt