1

I'm using Python's ctypes library to call my C code. My problem is that when I try to create a c_float, I seem to obtain a slightly different value to what I set.

For example

print(value)
print(c_float(value))

0.2
c_float(0.20000...298...)

How can I avoid this?

d33tah
  • 10,999
  • 13
  • 68
  • 158
Xabi E
  • 251
  • 2
  • 3
  • 15
  • Floating point numbers are often only approximations of the numbers you're trying to represent. `c_float(0.2)` will never be *exactly* 0.2 - it will always have inaccuracy is the lower-order bits. (The Python float has similar error.) – Alex Riley Jun 01 '15 at 11:11
  • 1
    Sorry, but that's just the way floating point numbers work. Floats are stored in binary, and 0.2 decimal == 1/5 = 3/15, so in binary that's 0.001100110011...See [Why Are Floating Point Numbers Inaccurate?](http://stackoverflow.com/questions/21895756/why-are-floating-point-numbers-inaccurate) for more info. – PM 2Ring Jun 01 '15 at 11:14

3 Answers3

3

Jan Rüegg is right - this is just how floats work.

If you're wondering why this only shows up with c_float, it's because

  • c_floats print as "c_float({!r}).format(self.value). self.value is a double-precision Python float.

  • Python's float type prints the shortest representation that converts to the floating point number, so although float(0.2) is not exact it can still be printed in short form.

The inaccuracy in c_float(0.2) is high enough to make it closer to

0.20000000298023223876953125

than to

0.200000000000000011102230246251565404236316680908203125

Since float(0.2) represents the later, the short form of "0.2" cannot be used.

Veedrac
  • 58,273
  • 15
  • 112
  • 169
1

Python's float corresponds to a C double, typically 64 bits wide. On the other hand a ctypes c_float corresponds to a C float, typically 32 bits wide. This is why you observe a degradation in accuracy - it is expected when representing a number inexactly with a narrower type.

c_float's __repr__ adds to the confusion by converting the number back to a Python float in order to print it, so its output includes additional unnecessary digits. 32-bit floats can be printed using 9 significant digits, while 64-bit floats require 17. The extra digits carry no additional information and make it look like the number has been corrupted.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
0

Floats have a fixed precision, and cannot necessarily represent finite numbers in decimal representation exactly.

On this website you can see how the float is actually stored in memory. If you enter "0.2" in "Decimal Representation", you can see how it is converted to a hex number, and that the stored number is exactly the number you noticed.

Jan Rüegg
  • 9,587
  • 8
  • 63
  • 105