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'