encoding a float

Discussion in 'C++' started by Fei Liu, Mar 27, 2007.

  1. Fei Liu

    Fei Liu Guest

    hurcan solter wrote:
    > Hi all, I am trying to convert a float value to a octet stream for
    > transmission, I came up with solution like
    >
    > float deneme=3.14156789;
    > float deneme2=0.0;
    > vector<unsigned char> vec; //this is my buffer can con contain
    > other things besides this float
    >
    > int* val=reinterpret_cast<int*>(&deneme); // gives me jeebies
    > vec.push_back((unsigned char) ((*val >> 24) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 16) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 8) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 0) & 0xFF ));
    > int val2=0;
    > int _pos=0;
    > val2+= ((int)vec[_pos++] & 0xFF) << 24;
    > val2+= ((int)vec[_pos++] & 0xFF) << 16;
    > val2+= ((int)vec[_pos++] & 0xFF) << 8;
    > val2+= ((int)vec[_pos++] & 0xFF) << 0;
    > deneme2=*reinterpret_cast<float*>(&val2); //ditto
    >
    > it works, but i am not sure that this is the Right Way to do, I
    > wonder if there is
    > a safer or cleaner way? I tried memcpy to treat the vector as if
    > an array it didn't
    > work out well( although, It should work right?)
    > Any pointers would be greatly appreciated...
    > hurcan
    >
    >


    Did you look into more general framework such as soap or yaml? Boost
    also has a primitive serialization/deserialization framework.

    Fei
    Fei Liu, Mar 27, 2007
    #1
    1. Advertising

  2. Hi all, I am trying to convert a float value to a octet stream for
    transmission, I came up with solution like

    float deneme=3.14156789;
    float deneme2=0.0;
    vector<unsigned char> vec; //this is my buffer can con contain
    other things besides this float

    int* val=reinterpret_cast<int*>(&deneme); // gives me jeebies
    vec.push_back((unsigned char) ((*val >> 24) & 0xFF ));
    vec.push_back((unsigned char) ((*val >> 16) & 0xFF ));
    vec.push_back((unsigned char) ((*val >> 8) & 0xFF ));
    vec.push_back((unsigned char) ((*val >> 0) & 0xFF ));
    int val2=0;
    int _pos=0;
    val2+= ((int)vec[_pos++] & 0xFF) << 24;
    val2+= ((int)vec[_pos++] & 0xFF) << 16;
    val2+= ((int)vec[_pos++] & 0xFF) << 8;
    val2+= ((int)vec[_pos++] & 0xFF) << 0;
    deneme2=*reinterpret_cast<float*>(&val2); //ditto

    it works, but i am not sure that this is the Right Way to do, I
    wonder if there is
    a safer or cleaner way? I tried memcpy to treat the vector as if
    an array it didn't
    work out well( although, It should work right?)
    Any pointers would be greatly appreciated...
    hurcan


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    hurcan solter, Mar 27, 2007
    #2
    1. Advertising

  3. Fei Liu

    red floyd Guest

    hurcan solter wrote:
    > Hi all, I am trying to convert a float value to a octet stream for
    > transmission, I came up with solution like
    >
    > float deneme=3.14156789;
    > float deneme2=0.0;
    > vector<unsigned char> vec; //this is my buffer can con contain
    > other things besides this float
    >
    > int* val=reinterpret_cast<int*>(&deneme); // gives me jeebies
    > vec.push_back((unsigned char) ((*val >> 24) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 16) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 8) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 0) & 0xFF ));


    Gener
    > int val2=0;
    > int _pos=0;
    > val2+= ((int)vec[_pos++] & 0xFF) << 24;
    > val2+= ((int)vec[_pos++] & 0xFF) << 16;
    > val2+= ((int)vec[_pos++] & 0xFF) << 8;
    > val2+= ((int)vec[_pos++] & 0xFF) << 0;
    > deneme2=*reinterpret_cast<float*>(&val2); //ditto
    >
    > it works, but i am not sure that this is the Right Way to do, I
    > wonder if there is
    > a safer or cleaner way? I tried memcpy to treat the vector as if
    > an array it didn't
    > work out well( although, It should work right?)
    > Any pointers would be greatly appreciated...
    > hurcan


    What about:

    float deneme = 3.14159;
    const unsigned char *const tmp_p =
    reinterpret_cast<unsigned char *>(&deneme);
    v.assign(tmp_p, tmp_p + sizeof(&deneme);

    float deneme2 = 0;
    std::copy(tmp_p.begin(), tmp_p + sizeof(deneme2),
    reinterpret_cast<unsigned char *>(&deneme2));

    You don't need to worry about byte ordering, etc in an int, or
    shift/masking. Just use direct copy.

    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    red floyd, Mar 27, 2007
    #3
  4. In comp.lang.c++.moderated hurcan solter <> wrote:
    > Hi all, I am trying to convert a float value to a octet stream for
    > transmission, I came up with solution like


    > [ type-punning code elided ]


    Whatever you do, follow http://www.ietf.org/rfc/rfc4506.txt .


    > Any pointers would be greatly appreciated...


    http://xstream.sourceforge.net/ , if an LGPL library works
    for you. If not, you can study their XDR code and reimplement
    it from scratch, taking care not to create a derivative work.


    --
    pa at panix dot com

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Pierre Asselin, Mar 27, 2007
    #4
  5. On 2007-03-27 18:00, hurcan solter wrote:
    > Hi all, I am trying to convert a float value to a octet stream for
    > transmission, I came up with solution like
    >
    > float deneme=3.14156789;
    > float deneme2=0.0;
    > vector<unsigned char> vec; //this is my buffer can con contain
    > other things besides this float
    >
    > int* val=reinterpret_cast<int*>(&deneme); // gives me jeebies
    > vec.push_back((unsigned char) ((*val >> 24) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 16) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 8) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 0) & 0xFF ));
    > int val2=0;
    > int _pos=0;
    > val2+= ((int)vec[_pos++] & 0xFF) << 24;
    > val2+= ((int)vec[_pos++] & 0xFF) << 16;
    > val2+= ((int)vec[_pos++] & 0xFF) << 8;
    > val2+= ((int)vec[_pos++] & 0xFF) << 0;
    > deneme2=*reinterpret_cast<float*>(&val2); //ditto
    >
    > it works, but i am not sure that this is the Right Way to do, I
    > wonder if there is
    > a safer or cleaner way? I tried memcpy to treat the vector as if
    > an array it didn't
    > work out well( although, It should work right?)
    > Any pointers would be greatly appreciated...
    > hurcan


    Seems a bit convoluted. What you want is to be able to treat the double
    as an array of unsigned chars, I'd do something like this:

    #include <iostream>

    int main()
    {
    std::cout.precision(10);
    double orig = 2134.4325;
    std::cout << orig << std::endl;

    unsigned char* bytes = reinterpret_cast<unsigned char*>(&orig);

    for (int i = 0; i < sizeof(double); ++i)
    {
    std::cout << std::hex << (int)bytes << std::endl;
    }

    double res = *reinterpret_cast<double*>(bytes);

    std::cout << res << std::endl;

    std::cout << (orig == res) << std::endl;
    }

    So what I do is to cast a pointer to the double to a pointer to unsigned
    char, and as long as I know what type it was from the beginning I can
    get the length of the array using sizeof().

    As for sending the data there might be some problems. As long as the
    sending and receiving computers have the same endianness there should be
    no problem but if they don't you have to take that into account.

    --
    Erik Wikström


    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=, Mar 27, 2007
    #5
  6. Fei Liu

    James Kanze Guest

    On Mar 27, 6:00 pm, "hurcan solter" <> wrote:
    > Hi all, I am trying to convert a float value to a octet stream


    In what format?

    > for
    > transmission, I came up with solution like


    > float deneme=3.14156789;
    > float deneme2=0.0;
    > vector<unsigned char> vec; //this is my buffer can con contain
    > other things besides this float


    > int* val=reinterpret_cast<int*>(&deneme); // gives me jeebies
    > vec.push_back((unsigned char) ((*val >> 24) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 16) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 8) & 0xFF ));
    > vec.push_back((unsigned char) ((*val >> 0) & 0xFF ));
    > int val2=0;
    > int _pos=0;
    > val2+= ((int)vec[_pos++] & 0xFF) << 24;
    > val2+= ((int)vec[_pos++] & 0xFF) << 16;
    > val2+= ((int)vec[_pos++] & 0xFF) << 8;
    > val2+= ((int)vec[_pos++] & 0xFF) << 0;
    > deneme2=*reinterpret_cast<float*>(&val2); //ditto


    > it works, but i am not sure that this is the Right Way to do, I
    > wonder if there is
    > a safer or cleaner way?


    The first question is the one above: what is the desired format.
    The above will only work if the internal format of a float
    corresponds exactly to the desired format. And of course, it
    also depends on int being the same size as float; I've definitly
    worked on machines where it is smaller.

    > I tried memcpy to treat the vector as if
    > an array it didn't
    > work out well( although, It should work right?)


    To memcpy, you'd have to first increase the size of the vector,
    then pass the address of the target element. And of course,
    memcpy is even less portable than the above; it can fail between
    two different machines even if both use IEEE floating point (and
    I've seen at least one case where it failed between two
    different versions of the same compiler, on the same platform).

    --
    James Kanze (GABI Software) mailto:
    Conseils en informatique orient?e objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    James Kanze, Mar 27, 2007
    #6
  7. Fei Liu

    Guest

    >
    > > Hi all, I am trying to convert a float value to a octet stream

    >


    I have a similar problem. However, I am working within the same
    machine, passing float/double from a JVM to native code. Currently, I
    am assuming that for JNI implementations of the JVM, sizeof(jint) ==
    sizeof(jfloat) and sizeof(jlong) == sizeof(jdouble) but this might not
    be safe. I can only assume that a JVM can successfully encode a Java
    float as a C++ jfloat and a Java double as a C++ jdouble.

    >
    > The first question is the one above: what is the desired format.
    > The above will only work if the internal format of a float
    > corresponds exactly to the desired format. And of course, it
    > also depends on int being the same size as float; I've definitly
    > worked on machines where it is smaller.
    >
    > > I tried memcpy to treat the vector as if
    > > an array it didn't
    > > work out well( although, It should work right?)

    >
    > To memcpy, you'd have to first increase the size of the vector,
    > then pass the address of the target element. And of course,
    > memcpy is even less portable than the above; it can fail between
    > two different machines even if both use IEEE floating point (and
    > I've seen at least one case where it failed between two
    > different versions of the same compiler, on the same platform).
    >


    What if I reinterpret the pointer to jdouble and jfloat as an unsigned
    char* and then encode as a hexstring. Won't this work as long as my
    JVM that produces the doubles and floats is the same machine and
    process that consumes them within the native code?

    Andy



    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    , Mar 28, 2007
    #7
  8. On 28 Mar, 08:39, "" <>
    wrote:
    > > > Hi all, I am trying to convert a float value to a octet stream

    >
    > I have a similar problem. However, I am working within the same
    > machine, passing float/double from a JVM to native code. Currently, I
    > am assuming that for JNI implementations of the JVM, sizeof(jint) ==
    > sizeof(jfloat) and sizeof(jlong) == sizeof(jdouble) but this might not
    > be safe. I can only assume that a JVM can successfully encode a Java
    > float as a C++ jfloat and a Java double as a C++ jdouble.
    >
    >
    >
    >
    >
    > > The first question is the one above: what is the desired format.
    > > The above will only work if the internal format of a float
    > > corresponds exactly to the desired format. And of course, it
    > > also depends on int being the same size as float; I've definitly
    > > worked on machines where it is smaller.

    >
    > > > I tried memcpy to treat the vector as if
    > > > an array it didn't
    > > > work out well( although, It should work right?)

    >
    > > To memcpy, you'd have to first increase the size of the vector,
    > > then pass the address of the target element. And of course,
    > > memcpy is even less portable than the above; it can fail between
    > > two different machines even if both use IEEE floating point (and
    > > I've seen at least one case where it failed between two
    > > different versions of the same compiler, on the same platform).

    >
    > What if I reinterpret the pointer to jdouble and jfloat as an unsigned
    > char* and then encode as a hexstring. Won't this work as long as my
    > JVM that produces the doubles and floats is the same machine and
    > process that consumes them within the native code?


    Might be, it certainly seems safer than assuming things about the size
    of things. But unless this is a performance-critical part I think it
    might be worth converting the ints, doubles, etc to a human readable
    format (text) and then convert back. This way you can be sure that the
    values are preserved.

    --
    Erik Wikström



    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    =?iso-8859-1?q?Erik_Wikstr=F6m?=, Mar 28, 2007
    #8
  9. Fei Liu

    James Kanze Guest

    On Mar 28, 8:39 am, "" <>
    wrote:
    > > > Hi all, I am trying to convert a float value to a octet stream


    > I have a similar problem. However, I am working within the same
    > machine, passing float/double from a JVM to native code. Currently, I
    > am assuming that for JNI implementations of the JVM, sizeof(jint) ==
    > sizeof(jfloat) and sizeof(jlong) == sizeof(jdouble) but this might not
    > be safe. I can only assume that a JVM can successfully encode a Java
    > float as a C++ jfloat and a Java double as a C++ jdouble.


    JNI is a different situation, and you should check the JNI
    documentation to be sure, but I believe that at the JNI
    interface, you'll get native format, regardless of what the JVM
    uses internally.

    > > The first question is the one above: what is the desired format.
    > > The above will only work if the internal format of a float
    > > corresponds exactly to the desired format. And of course, it
    > > also depends on int being the same size as float; I've definitly
    > > worked on machines where it is smaller.


    > > > I tried memcpy to treat the vector as if
    > > > an array it didn't
    > > > work out well( although, It should work right?)


    > > To memcpy, you'd have to first increase the size of the vector,
    > > then pass the address of the target element. And of course,
    > > memcpy is even less portable than the above; it can fail between
    > > two different machines even if both use IEEE floating point (and
    > > I've seen at least one case where it failed between two
    > > different versions of the same compiler, on the same platform).


    > What if I reinterpret the pointer to jdouble and jfloat as an unsigned
    > char* and then encode as a hexstring. Won't this work as long as my
    > JVM that produces the doubles and floats is the same machine and
    > process that consumes them within the native code?


    It depends on who's reading the stream, and why. I don't really
    understand what you are trying to do; you can pass float and
    double directly over the JNI interface, and they should be in
    native format, ready for immediate use. If you're streaming
    data (e.g. into a ByteArray), then you have to follow the same
    rules as everyone else: decide on a format, and ensure that
    everyone codes to it. (Converting to a hex string seems off
    hand to combine the worst aspects of both binary and text. I
    wouldn't do it unless it was required by some external format.)

    --
    James Kanze (GABI Software) mailto:
    Conseils en informatique orient?e objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    James Kanze, Mar 28, 2007
    #9
  10. Fei Liu

    John Moeller Guest

    On Mar 28, 12:39 am, "" <>
    wrote:
    > I have a similar problem. However, I am working within the same
    > machine, passing float/double from a JVM to native code. Currently, I
    > am assuming that for JNI implementations of the JVM, sizeof(jint) ==
    > sizeof(jfloat) and sizeof(jlong) == sizeof(jdouble) but this might not
    > be safe. I can only assume that a JVM can successfully encode a Java
    > float as a C++ jfloat and a Java double as a C++ jdouble.
    >

    ....
    >
    > What if I reinterpret the pointer to jdouble and jfloat as an unsigned
    > char* and then encode as a hexstring. Won't this work as long as my
    > JVM that produces the doubles and floats is the same machine and
    > process that consumes them within the native code?


    There may be better alternatives depending upon what you want to do.
    If you want to encode the floating-point numbers as bytes, and you
    have a lot of them, you may want to use a java.nio.ByteBuffer. You
    can create a double or float view of the ByteBuffer, and the byte
    order is always big-endian by default. If the ByteBuffer is created
    with allocateDirect, you can pass it to native functions, and get
    access to the byte data directly in native code. You can do the same
    in reverse to get it back.

    If you're talking only a few values, you probably just want to use the
    text-encoding methods described earlier. The only problem with text-
    encoding numbers (especially floating-point), however, is
    localization. E.g., a "," in Germany means the same as a "." in the
    U.S. or Britain. We've run into this problem before at my company,
    and we decided that internally-represented numbers would just use the
    one localization.


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    John Moeller, Mar 28, 2007
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andy
    Replies:
    7
    Views:
    6,243
    Roedy Green
    May 10, 2004
  2. Jim West
    Replies:
    4
    Views:
    1,407
    Jeff Schwab
    Jan 16, 2004
  3. Jukka Lehtonen

    operator== (float, float)

    Jukka Lehtonen, Aug 4, 2004, in forum: C++
    Replies:
    5
    Views:
    2,410
    Jukka Lehtonen
    Aug 5, 2004
  4. bd
    Replies:
    0
    Views:
    608
  5. Carsten Fuchs
    Replies:
    45
    Views:
    1,509
    James Kanze
    Oct 8, 2009
Loading...

Share This Page