2

I want to send float values from java to c++ over a socket, without any third party library and byte order safely.

On the C++ side, I handle the byte order (using htonf from the beej's guide). But how can I handle the byte-order in java? For int, the byte order seems handled well by the java socket but float doesn't transmit correct values. Or is conversion to strings the only way to send floats safely?

java:

DataOutputStream out;
out.writeFloat(val);

C++ conversion method from beej's guide:

float ntohf(uint32_t p)
{
    float f = ((p>>16)&0x7fff); // whole part
    f += (p&0xffff) / 65536.0f; // fraction

    if (((p>>31)&0x1) == 0x1) { f = -f; } // sign bit set

    return f;
}
user2212461
  • 3,105
  • 8
  • 49
  • 87
  • 4
    Why not send as string and convert to float? – Sorter Jul 16 '14 at 18:29
  • 2
    Did it occur to you to consult the spec? DataOutputStream writeFloat: "Converts the float argument to an int using the floatToIntBits method in class Float, and then writes that int value to the underlying output stream as a 4-byte quantity, high byte first. If no exception is thrown, the counter written is incremented by 4." And floatToIntBits: "Bit 31 (the bit that is selected by the mask 0x80000000) represents the sign of the floating-point number. .... etc" – Hot Licks Jul 16 '14 at 18:53
  • 2
    @DeepakMishra BECAUSE AN EXTRA 16 BYTES MATTERS – Christopher Wirt Jul 16 '14 at 18:53
  • (I can't tell what your `ntohf` function is supposed to do. It's certainly not converting an IEEE float stored in an `int` into `float`.) – Hot Licks Jul 16 '14 at 18:56
  • All you should need to do on the C++ side, assuming IEEE float is the standard, is (optionally) convert byte order. – Hot Licks Jul 16 '14 at 18:57
  • 1
    Consider using strictfp to guarantee same bits in float on different hardware. Also ByteBuffer can give your flexibility (via http://docs.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html#putFloat(float) ) to operate on float's bytes. – Denis Gladkiy Jul 16 '14 at 19:08

1 Answers1

2

That ntohf function interprets p as fixed fixed point number. 15 bits for whole part, 16 bits for fraction and 1 for sign. That's not the format used by Java.

Most modern machines have compatible floating point representation. You will be pretty safe passing the bits directly. For example:

float f = reinterpret_cast<float&>(ntohl(n));
Piotr Praszmo
  • 17,928
  • 1
  • 57
  • 65
  • The only issue being that byte order may (in fact, probably will) need adjustment. – Hot Licks Jul 16 '14 at 18:59
  • I need automatic byte order adjustment – user2212461 Jul 16 '14 at 19:05
  • 2
    `ntohl` takes care of that. – Piotr Praszmo Jul 16 '14 at 19:06
  • 3
    +1, but note that the `reinterpret_cast` may not work with some compilers which respect strict aliasing; it's more portable to use a union, see http://stackoverflow.com/a/13982359/9530 . – Adam Rosenfield Jul 16 '14 at 19:12
  • @user2212461 - You know that Java sent the data big-endian. You need to know whether the receiving system played with the byte order when it received the data or not, and adjust accordingly. This would be *exactly* the same transformation (or not) that you would do on an `int` value. – Hot Licks Jul 16 '14 at 21:50