Home > Net >  Converting ctype float to python float properly
Converting ctype float to python float properly

Time:03-17

I am receiving a ctype c_float via a C library that I would like to convert to a regular python float.

The problem is that ctype uses 32 bit precision while python uses 64 bit precision.

Say a user enters the number 1.9 into the C user interface. The number is represented as 1.899999976158142. When I print it on the C side, this representation is taken into account and I get an output of 1.9.

However on the python side, when I convert the c_float to python with its higher precision, then the number will not be treated as a 1.9 when printing, but as 1.899999976158142 instead.

How do I solve this?

I found a way, but it's a bit clunky (and unnecessarily inefficient), so I was hoping for a more elegant solution:

float_c = ctypes.c_float(1.9)  # c_float(1.899999976158142)

float_32 = float_c.value  # 1.899999976158142
float_str = f"{float_32:g}"  # "1.9"
float_py = float(float_str)  # 1.9

Since the precision will only become a problem during conversion to string (printing and writing to file), I could just live with it and omit the last step, but I find it inelegant to keep the number in its "problematic" state where I have to worry about the conversion every time I may want to print it.

Instead I think it's cleaner to just convert it once at the handover point between the C lib and python and never worry about it again.

So should I just do the conversion from c_float to python float like this or is there a better way?

CodePudding user response:

A possible workaround is to use numpy's float32:

>>> float_c = ctypes.c_float(1.9)
>>> np.float32(float_c)
1.9

CodePudding user response:

People have pointed out that the number converted to float64 from float32 is exactly the same value stored in C and you need knowledge of the original number to meet your definition of more precise, but you can round the resulting number to the same number of decimal places as C (or what you think the user intended) and the resulting float64 will be closer to that value:

>>> import struct
>>> x=struct.unpack('f',struct.pack('f',1.9))[0] # trick to achieve converted number
>>> x
1.899999976158142
>>> y=round(x,7)  # or to whatever places you expect the user to enter
>>> y
1.9
>>> format(x,'.20f')
'1.89999997615814208984'
>>> format(y,'.20f')
'1.89999999999999991118'
  • Related