How to serialize a float?

Of course you can just cast it to char array and write(or send) it like that, but that would only work if all machines have the same byte order for floats.

For integers it's simple, you can serialize it by doing
1
2
3
4
	buffer[0] = (val & 0xff000000) >> 24;
	buffer[1] = (val & 0x00ff0000) >> 16;
	buffer[2] = (val & 0x0000ff00) >> 8;
	buffer[3] = (val & 0x000000ff);

And then deserialize it by doing
1
2
3
4
5
	val = 0;
	val |= ((long)buffer[0]) << 24;
	val |= ((long)buffer[1]) << 16;
	val |= ((long)buffer[2]) << 8;
	val |= ((long)buffer[3]);

This way you know that the significant bits are sent first.

How do you serialize floats when writing it to a file or sending it via socket?
both float and int are 4 bytes so you should be able to do the exact same thing with float.
In case if compiler won't let you, you could treat float as an int:
1
2
3
4
5
float f;
    buffer[0] = ((long)f & 0xff000000) >> 24;
    buffer[1] = ((long)f & 0x00ff0000) >> 16;
    buffer[2] = ((long)f & 0x0000ff00) >> 8;
    buffer[3] = ((long)f & 0x000000ff);


I've not come across the situation where I ever needed something like that.
What kind of machine has the float's byte order different?
Last edited on
Gyiove, dude I know what you wanted to do, but doing "(long)f" is actually going to round your float to nearest integer value.
Instead if you used "*(long*)&f" you would get a long int which is located at the same address as the float and thus has the same bits.
Gyiove wrote:
both float and int are 4 bytes

No, not necessarily. This isn't true in a significant number of cases. Also, the C-style cast will do a type conversion, not reinterpretation. Use reinterpret_cast on the address of your float instead.

What kind of machine has the float's byte order different?

AMD and Intel processors are big and little-endian, respectively. Other architectures, (for example, ARM v3+), support both byte orders. Rarely, the floating-point byte order doesn't match the processors' endianness. You can't assume one or the other. Convert to network byte order before sending it.

zoran404 wrote:
How do you serialize floats when writing it to a file or sending it via socket?

Write it out as text. That's foolproof.

If you must write it out in a binary format, then you can store it however you want, as long as you don't assume anyone else can read it back. For local data files, you can just write out the bytes in host order, or if you care about being able to share it, convert it to network byte order.

If you're reading/writing it from/to a socket, convert it (if you need to) using hton[ls]() and ntoh[ls]().
Last edited on
I ended up casting float to long and double to long long and just using the algorithm from my first post to serialize those.

mbozzi, The problem I was having was that there is no hton and ntoh for 64 bit variables.
You're right. But float in C and C++ is (usually) IEEE754 single-precision floating point, specifically the binary32 variety - the size accepted by htonl.

Still, the representation of floating-point (float or double) values across different architectures isn't necessarily consistent with endianness across different architectures. If you need to share the data across platforms and with different programs, you should probably use something like XDR.

See
http://man7.org/linux/man-pages/man3/xdr.3.html

Or, just write text instead of binary.
Last edited on
Topic archived. No new replies allowed.