Boost logo

Boost :

Subject: Re: [boost] [serialization] round-trip serialization of float
From: John Salmon (john_at_[hidden])
Date: 2013-01-14 11:11:46


On Fri, Jan 11, 2013 at 3:45 PM, Robert Ramey <ramey_at_[hidden]> wrote:

> Adam Lerer wrote:
> >>> a) not every binary floating number has en exact representation when
> >>> rendered as decimal.
> > True, but if max_digits10 digits is used, you can at least guarantee
> > that the binary representation will deserialize as the same float.
> > This is very helpful for common use cases of the serialization library
> >
> > I understand that float serialization cannot be guaranteed to work
> > correctly in all cases. That said, the precision used for float
> > serialization is a choice, and some choices are better than others. It
> > seems to me that the choice of max_digits10 (or even better, Paul's
> > alternative formula to work around the VS bug) is superior to
> > digits10+2.
> >
> > It might also be helpful to note that lexical_cast uses exactly the
> > formula that Paul recommends. In lcast_precision.hpp:
> >
> > BOOST_STATIC_CONSTANT(unsigned long, precision_bin =
> > 2UL + limits::digits * 30103UL / 100000UL
> > );
> >
>
> Feel free to add a trac item for this
>
> Robert Ramey
>
>
>
FWIW, here's a patch that calls boost::detail::lcast_get_precision instead
of digits10+2. It appears that the lexical_cast authors have thought
through several portability/compatibility issues. Serialization might as
well benefit from their work.

The patch also has an overload of save(long double) which follows the same
pattern as save(float) and save(double).

John Salmon

diff -Naur boost_1_52_0.orig/boost/archive/basic_text_oprimitive.hpp
boost_1_52_0/boost/archive/basic_text_oprimitive.hpp
--- boost_1_52_0.orig/boost/archive/basic_text_oprimitive.hpp 2011-01-19
12:33:55.000000000 -0500
+++ boost_1_52_0/boost/archive/basic_text_oprimitive.hpp 2013-01-14
10:21:26.000000000 -0500
@@ -33,6 +33,7 @@
 #include <boost/config.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/detail/workaround.hpp>
+#include <boost/detail/lcast_precision.hpp>
 #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
 #include <boost/archive/dinkumware.hpp>
 #endif
@@ -130,7 +131,7 @@
             boost::serialization::throw_exception(
                 archive_exception(archive_exception::output_stream_error)
             );
- os << std::setprecision(std::numeric_limits<float>::digits10 + 2);
+ os <<
std::setprecision(boost::detail::lcast_get_precision<float>());
         os << t;
     }
     void save(const double t)
@@ -140,7 +141,17 @@
             boost::serialization::throw_exception(
                 archive_exception(archive_exception::output_stream_error)
             );
- os << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+ os <<
std::setprecision(boost::detail::lcast_get_precision<double>());
+ os << t;
+ }
+ void save(const long double t)
+ {
+ // must be a user mistake - can't serialize un-initialized data
+ if(os.fail())
+ boost::serialization::throw_exception(
+ archive_exception(archive_exception::output_stream_error)
+ );
+ os << std::setprecision(boost::detail::lcast_get_precision<long
double>());
         os << t;
     }
     BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk