Question

Im trying to send a unsigned int data from a C server to a python client. The requirement is to send a negative float value to the client. currently the number is -5.700 and I have 2 problems. 1) I dont have a clue on how to retain the negativeness within uint32_t, im using the MSB as a flag bit to get around it. Is this fine? Does anyone has better suggestions?

2) I tried typecasting float 5.700 to uint32_t, i.e uint32_t fops = *(uint32_t*)(&float_var) //float_var is 5.700 And fops was assigned value 0x00..40b66666 which is being sent to the python client. now how do I retrieve the float back from this value at the client?

update: As Mats suggested python struct unpacks -ve floats perfectly so there is no need to use a flag bit.

Was it helpful?

Solution

The simplest solutions are nearly always best: Make it a string, and transfer that, rather than a binary floating point representation. That way, you don't have to worry about differences in floating point representation or how to make Python "understand" your binary floating point value.

Edit1: However, if you transfer a 32-bit integer to a Python data object: I expect floatdata = struct.unpack("f", data) should do the trick.

Edit2: Documentation for struct.unpack (and struct.pack)

Edit3: The struct.unpack does assume both machines use the same floating point format. This means the software isn't widely portable. But it should work ok on most commonly available platforms.

OTHER TIPS

The casting on the C side was just to take the 4 bytes representing a float and stick it into the fops variable for transfer. You transfer that to the python client somehow and its still the 4 bytes that represents the floating point number. You can use the struct module to take those 4 bytes and build a python float.

(edit) the hight bit is the problem. The uint32_t cast left off the high bit and as soon as that is set (0xc0b66666) as opposed to (0x40b66666), it works correctly in python. So, you could set MSB manually and it should work.

>>> import struct
>>> buf=struct.pack('i', 0xc0b66666) # this is like the C cast to uint32_t
>>> len(buf)
4
>>> struct.unpack('f', buf)[0]
-5.699999809265137

You can use the C math functions frexpf() to extract the exponent and mantissa of the float. Then, you can use ldexp() in Python to reconstitute the two.

The exponent is returned as a signed integer, and the mantissa a signed float in the interval [.5, 1) or [-.5, -1), depending on sign of the float.

How you decide to encode and decode this information to and from a 32 bit unsigned number is up to you. But, assume you allow 16 bits for the mantissa. Then, you can multiply the mantissa by 215, and then use the 16 bits to represent the rounded integer value of the result in 2's complement. The receiver could then take the 16 bits, convert into a signed integer, and divide by 215.

The other 16 bits of your 32 bits could be used to represent the exponent in 2's complement as well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top