The C++ standard does not discuss the underlying layout of float and double types, only the range of values they should represent. (This is also true for signed types, is i
Take a look at the (old) gtypes.h file implementation in glib 2 - it includes the following:
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
union _GFloatIEEE754
{
gfloat v_float;
struct {
guint mantissa : 23;
guint biased_exponent : 8;
guint sign : 1;
} mpn;
};
union _GDoubleIEEE754
{
gdouble v_double;
struct {
guint mantissa_low : 32;
guint mantissa_high : 20;
guint biased_exponent : 11;
guint sign : 1;
} mpn;
};
#elif G_BYTE_ORDER == G_BIG_ENDIAN
union _GFloatIEEE754
{
gfloat v_float;
struct {
guint sign : 1;
guint biased_exponent : 8;
guint mantissa : 23;
} mpn;
};
union _GDoubleIEEE754
{
gdouble v_double;
struct {
guint sign : 1;
guint biased_exponent : 11;
guint mantissa_high : 20;
guint mantissa_low : 32;
} mpn;
};
#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
#error unknown ENDIAN type
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
glib link
Found this old thread. One solution which solves a fair deal of cases is missing - using fixed point, passing integers with a known scaling factor using built-in casts in either end. Thus, you don't have to bother with the underlying floating point representation at all.
There are of course drawbacks. This solution assumes you can have a fixed scaling factor and still get both the range and resolution needed for the particular application. Furthermore, you convert from your floating point to fixed point at the serialization end and convert back at deserialization, introducing two rounding errors. However, over the years I have found fixed point is enough for my needs in almost all cases and it is reasonably fast too.
A typical case for fixed point would be communication protocols for embedded systems or other devices.
What's wrong with a human readable format.
It has a couple of advantages over binary:
Disadvantage:
htonl()
)To output a double at full precision:
double v = 2.20;
std::cout << std::setprecision(std::numeric_limits<double>::digits) << v;
OK. I am not convinced that is exactly precise. It may lose precision.