'Converting ctype float to python float properly
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?
Solution 1:[1]
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'
Solution 2:[2]
A possible workaround is to use numpy's float32:
>>> float_c = ctypes.c_float(1.9)
>>> np.float32(float_c)
1.9
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Mark Tolonen |
| Solution 2 | Anis R. |
