-----Original Message----- From: Boost-users [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Robert Ramey Sent: 28 January 2015 15:17 To: boost-users@lists.boost.org Subject: Re: [Boost-users] [Serialization] XML: float format is scientific instead of human-readable since Boost 1.57
Frank Stähr wrote
I compiled it with VS 2013 for 32 bit. The output file has the line:
2.99999999999999990e-002 In Boost 1.55 it was much better human-readable: 0.03.Is this behaviour (this change) intended? In any case, what is the best way to format floats and doubles? (i. e. a manipulator for the of stream?)
This is surely an unintended side effect of changes to guarantee correct "round tripping" of floating point numbers. That is that the the floating point number read in is bit for bit the same as the floating point number written out.
This was seen as good thing.
Short answer:
If you want to be sure that what you get back from de-serialization is bit-for-bit identical to what you serialized,
then it is definitely a Good Thing.
For some MS compilers at least, it is also necessary to use scientific format for this to avoid some
very intermittent failures to 'round-trip' correctly. (This was discovered by a real-time user - and was only pinned down by random testing!)
Long Answer:
For more than you will want to know see:
Exploring Binary
But the other thing is that by setting precision to 17 lexical_cast is bloating the string representations of the doubles with lots of 9s in both Visual Studio 2010 and Visual Studio 2013. Setting precision to 15 instead prevents this, and makes the original test run faster even with Visual Studio 2013 (about 4 seconds rather than 10).
In order to be sure of 'round-tripping' one needs to output std::numeric_limits<FPT>::max_digits10 decimal digits. max_digits10 is 17 for double enough to ensure that all *possibly* significant digits are used. digits10 is 15 for double and using this will work for *your* example, but will fail to 'round-trip' exactly for *some* values of double. The reason for a rewrite *might* be that for VS <=11, there was a slight 'feature' ('feature' according to Microsoft, 'bug' according to many, though the C++ Standard does NOT require round-tripping to be exact. Recent GCC and Clang achieve exact round-tripping.) // The original value causing trouble using serialization was 0.00019075645054089487; // wrote 0.0019075645054089487 // read 0.0019075645054089489 // a increase of just 1 bit. // Although this test uses a std::stringstream, it is possible that // the same behaviour will be found with ALL streams, including cout and cin? // The wrong inputs are only found in a very narrow range of values: // approximately 0.0001 to 0.004, with exponent values of 3f2 to 3f6 // and probably every third value of significand (tested using nextafter). However, a re-test reveals that this 'feature' is still present using VS2013 (version 12.0). (This tests uses random double values to find round-trip or loopback failures). So the price of accuracy is lots of digits (and time to output and re-digest them) :-( Paul --- Paul A. Bristow Prizet Farmhouse Kendal UK LA8 8AB +44 (0) 1539 561830