Why is "c_float()" generating incorrect values?

Asked

Viewed 52 times

2

I am creating a program in Python - using the library ctypes - to read and write values in memory, and I want to be accurate in the size of the data to be read and written.

In this case, if the floating point value has a size of 4 bytes, its type should be float. If it has 8 bytes, it must be a double. For this, I am using the following code:

def get_type(value, size):
    return ctypes.c_float(value) if size <= 4 else ctypes.c_double(value)

The problem is that the ctypes.c_float, unlike ctypes.c_double, is always getting a value x.yz and turning into x.ab. In other words, it generates a different value after the point. See the examples below:

ctypes.c_float(590621.2148).value     # 590621.1875
ctypes.c_float(324456.234).value      # 324456.21875
ctypes.c_float(987.1).value           # 987.0999755859375
ctypes.c_float(456.234)               # 456.2340087890625

I know that the float is less precise than the guy double, but the problem is happening from the first decimal! Something curious that I noticed is that the smaller the number to the left of the dot, the smaller the error in the decimal numbers. See below:

ctypes.c_float(590621.2148).value # 590621.1875       -> Todos os decimais errados
ctypes.c_float(90621.2148).value  # 90621.2109375     -> Os 2 primeiros decimais corretos
ctypes.c_float(621.2148).value    # 621.2147827148438 -> Os 3 primeiros decimais corretos

For this reason, I entertained the idea that the problem was occurring due to the lack of space float to bear the value. But obviously, it’s impossible for that to be the reason, since this guy can carry numbers as high as 10 to the 38 - as far as I can remember.

My question is: what is this problem happening and what should I do to fix it? Remembering again that I don’t want to use the c_double for any floating point value that appears, only to "fix" the problem. I want to put each value in its correct type, by aesthetics and not to occupy unnecessary space.

  • Take a look in this table. ctypes.c_float and ctypes.c_double allocate the same amount of memory. And here ctypes.c_float and ctypes.c_double implement types internally C float and double which respectively use 4bytes and 8bytes.

  • @Augustovasques I looked at the table. Where did you see that both allocate the same amount of memory? It just says that both can be used for float in Python (since in Python, the only floating point type is float). If you use the function sizeof, will see that they have different sizes (4 bytes and 8 bytes). As for the second part, yes I know that, and that’s what I just said... What does all this have to do with the question after all?

  • See https://ideone.com/EPhw5x, what has to do with the question you are using a lower precision type with the same memory consumption.

  • @Augustovasques Yes, this is the size of its raw value in Python. But what about the size of the buffer created for it with CTYPE? See here: https://docs.python.org/3/library/ctypes.html#ctypes.sizeof

  • So from these 24 bytes to ctypes.c_float 4 are allocated to float in , 4 become empty and in the other 8 bytes are allocated to double. There is no computational advantage whatsoever.

  • @Augustovasques I have the impression that you are getting confused about something. These 24 bytes are not from C_FLOAT, they are of value float python itself. The attribute value returns a value float. Also, I need to pass the value to a CTYPE for me to use the functions of winapi.

  • Who is getting confused is you "this buffer" stays within 24 bytes of type float.

  • @Augustovasques I see now what you mean (although I have no idea how a primitive type of Python has been modified this way). Still, I’d like to know the problem with c_float, and bonus, why size is the same in practice, although the documentation says otherwise.

  • 1

    This ctype representation is useful when you want to serialize/deserialize binary data or export data or data pointer to a lib. To write directly into memory would be better to use the module structs

Show 4 more comments
No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.