|
Boost : |
From: Paul A Bristow (pbristow_at_[hidden])
Date: 2006-03-14 14:05:58
You are right to expect this, but apparently the Standard does not REQUIRE
it.
The formulae for the number of decimla digits required is given in
http://www2.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1822.pdf
which is derived from Kahan's paper:
http://http.cs.berkley.edu/~wkahan/ieee754status/ieee754.ps
max_decimal_digits = 2 + significand_digits * 3010/1000
For example:
#define FLT_MAXDIG10 (2+(FLT_MANT_DIG * 3010)/10000)
#define DBL_MAXDIG10 (2+ (DBL_MANT_DIG * 3010)/10000)
#define LDBL_MAXDIG10 (2+ (LDBL_MANT_DIG * 3010)/10000)
which yield the following values on typical implementations:
FLT_DIG 6, FLT_MAXDIG10 9
DBL_DIG 15, DBL_MAXDIG10 17
LDBL_DIG 19, LDBL_MAXDIG10 21
For C++, using numeric limits,
So it is convenient instead to use the following formula which can be
calculated at compile time:
2 + std::numeric_limits<double>::digits * 3010/10000;
HOWEVER, during my tests of VS 2005 BETA, float did not read back in
correctly (for 1/3 of values, off by 1 bit!), and when I queried this was
claimed by Microsoft to be 'by design'. Mysteriously, in the VS 2005 final
_release_, float and double (and thus long double == double) all work as
expected for a 'quality product'.
As far as I recollect, VS 7.1 also worked correctly for all FP types, so I
would surmise that the number of digits used for serialisation is
insufficient? For double, it should be 17. There do appear to be 17
digits, so I am slightly puzzled.
But:
I:\boost-06-01-13-0500\boost\archive\basic_text_oprimitive.hpp(124)
uses
os << std::setprecision(std::numeric_limits<double>::digits10 + 2);
and I suggest that this should be:
os << std::setprecision(2 + std::numeric_limits<double>::digits *
3030/10000);
HTH
Paul
-- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB Phone and SMS text +44 1539 561830, Mobile and SMS text +44 7714 330204 mailto: pbristow_at_[hidden] http://www.hetp.u-net.com/index.html http://www.hetp.u-net.com/Paul%20A%20Bristow%20info.html | -----Original Message----- | From: boost-bounces_at_[hidden] | [mailto:boost-bounces_at_[hidden]] On Behalf Of Paul Giaccone | Sent: 14 March 2006 17:39 | To: boost_at_[hidden] | Subject: [boost] [serialization] | Serialisation/deserialisation offloating-point values | | I'm having problems with deserialising floating-point (double) values | that are written to an XML file. I'm reading the values back in and | comparing them to what I saved to ensure that my file has | been written | correctly. However, some of the values differ in about the | seventeenth | significant figure (or thereabouts). | | I thought Boost serialization used some numerical limit to make sure | that values are serialised exactly to full precision, so what is | happening here? | | Example: | Value in original object, written to file: 0.0019075645054089487 | Value actually stored in file (by examination of XML file): | 0.0019075645054089487 [identical to value written to file] | Value after deserialisation: 0.0019075645054089489 | | It looks like there is a difference in the least-significant bit, as | examining the memory for these two values gives: | | Original value: b4 83 9b ca e7 40 5f 3f | Deserialised value: b5 83 9b ca e7 40 5f 3f | | (where the least-significant byte is on the left) | | Note the difference in the first bytes. | | I'm using Boost 1.33.1 with Visual Studio 7.1.3088 in debug mode. | | Paul
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk