Portability of binary serialization of double/float type in C++

后端 未结 9 2089
余生分开走
余生分开走 2020-11-27 15:50

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

相关标签:
9条回答
  • 2020-11-27 16:25

    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

    0 讨论(0)
  • 2020-11-27 16:28

    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.

    0 讨论(0)
  • 2020-11-27 16:31

    What's wrong with a human readable format.

    It has a couple of advantages over binary:

    • It's readable
    • It's portable
    • It makes support really easy
      (as you can ask the user to look at it in their favorite editor even word)
    • It's easy to fix
      (or adjust files manually in error situations)

    Disadvantage:

    • It's not compact
      If this a real problem you can always zip it.
    • It may be slightly slower to extract/generate
      Note a binary format probably needs to be normalized as well (see 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.

    0 讨论(0)
提交回复
热议问题