deepsky
deepsky

Reputation: 875

How to do serialization of float numbers on network?

I found a piece of code to do the serialization of float numbers on network.

uint32_t htonf(float f)
{
    uint32_t p;
    uint32_t sign;

    if (f < 0) { sign = 1; f = -f; }
    else { sign = 0; }

    p = ((((uint32_t)f)&0x7fff)<<16) | (sign<<31); // whole part and sign
    p |= (uint32_t)(((f - (int)f) * 65536.0f))&0xffff; // fraction

    return p;
}

Spec: The above code is sort of a naive implementation that stores a float in a 32-bit number. The high bit (31) is used to store the sign of the number ("1" means negative), and the next seven bits (30-16) are used to store the whole number portion of the float. Finally, the remaining bits (15-0) are used to store the fractional portion of the number.

The others are fine but I cannot figure out what this means. How does this get us the 15-0 bits? Why do we need the "*65536.0f"?

p |= (uint32_t)(((f - (int)f) * 65536.0f))&0xffff

Anyone can explain on this?

Upvotes: 1

Views: 1727

Answers (2)

Mike Kale
Mike Kale

Reputation: 4133

f - (int)f

gives you the fractional part of the number. You want to store this fraction in 16 bits, so think of it as a fraction with 2^16 as the denominator. The numerator is:

(f - (int)f) * 65536.0f)

The rest just uses bit shifting to pack it up into the right bits in the 32 bit number. Then that 32 bit int is serialized on the network like any other 32 bit int, and presumably the opposite of the above routine is used to re-create a floating point number.

Upvotes: 5

Boann
Boann

Reputation: 50041

You could use a union.

uint32_t htonf(float f)
{
    union {
        float f1;
        uint32_t i1;
    };
    f1 = f;
    return i1;
}

Upvotes: -1

Related Questions