Subject: Re: [boost] [serialization] How are floating point values handled?
From: Robert Ramey (ramey_at_[hidden])
Date: 2013-08-07 15:02:23
John Maddock wrote:
> I can't find anything in the docs about how floating point types are
> handled by the serialization lib. It seems like text archives print
> however many digits are specified in the ostream's precision is that
> correct? If so I think this needs to be raised as a big red flag,
> because it means that floating point values, uniquely compared to
> other primitives, do not round trip by default. Except actually they
> do when using a binary archive.
> This actually raises a problem when using text archives with floating
> point data - if you want to be able to round trip the values, then
> how many digits precision should you set the stream to? Particularly
> if you're saving a complex structure containing different floating
> point types of differing precisions?
> I would have thought it would be better for the serialization lib to
> set the stream precision before outputting a primitive type - to
> std::numeric_limits<T>::max_digits10 (or
> std::numeric_limits<T>::digits10+2 if max_digits10 is not available).
> However, I recognize that this is a difficult issue!
lol - thanks for recognising that this is a difficult issue. It is reported
on a regular basis.
binary_?archive - no issue.
portable_binary_archives - doesn't support floating point numbers.
text archives - this depends on the std::stream to do the the conversion
to text and back again. It uses functions in this class to attempt to
set the precision to high enough number so that no more information
is lost than is necessary. Conversion to text and back again has some
inherent problems. Note that these have their root cause in
the std::stream implementations and design rather than the
serialization library itself.
a) there is not necessarily a one to one mapping of every ieee 754
number with a binary mantissa to a decimal representation.
My view is that on who relies on perfect round tripping of a
floating point number is making a design mistake. Leave
aside the fact that it cannot be portable between machines
with different floating point representations (and precisions).
It conflicts with what a floating point number really is. It's
an attempt to capture some continuous value to finite level
of precision. It generally represents some physical quantity
which generally can only be measured to a precision less
than that which our floating point representation can
represent. So I've very suspicious of any program which
requires perfect round tripping - if our program depends
on having more precision than that which can actually be
measured - what can theh program actually mean?
b) compilers/libraries don't handle NaN in a consistent way so
handling these is inherently non-portable.
I think I address this by trapping whenever one tries to serialize
a NaN. My reasoning was that it was a pain to implement,
and would be unreliable. I also feel (and felt) that anyone
actually trying to do this is making a mistake and should
think about what he's really doing. (I caught hell for say
this - anyone who does this doesn't know what he's doing.
Maybe it was the way I phrased it - oh well).
I'm pretty much sure that all this is not new you. I am in
awe of your accomplishments in the creation of boost libraries.
But I included the (verbose) response - because I like
to stir any pot presented to me.
FWIW- many years ago I attended a numerical analysis
class taught by professor William Kahan. It stuck with
me all my life. Only relatively recently, did I discover
his pivitol role in the creation of the ieee754 standard and
the intel 8087 processor. I had proposed him as a keynote
speaker at BoostCon - but no one had heard of him.
Floating point arithmetic is an incredibly rich topic - much
more than meets the eye.
Sorry if I got carried away.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk