This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: int casting to float results to a different value in memory
Type: behavior Stage: resolved
Components: ctypes, Library (Lib) Versions: Python 3.8
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: mark.dickinson, rhettinger, steven.daprano, tim.peters, yang8621
Priority: normal Keywords:

Created on 2021-04-26 02:52 by yang8621, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (7)
msg391876 - (view) Author: Huang Yang (yang8621) Date: 2021-04-26 02:52
from ctypes import *
import struct

i = int('7f94e57c', 16)
cp = pointer(c_int(i))
fp = cast(cp, POINTER(c_float))
print(fp.contents.value) # nan
print(struct.pack(">f", fp.contents.value).hex()) # 7fd4e57c

# value changed: 7f94e57c -> 7fd4e57c
msg391877 - (view) Author: Huang Yang (yang8621) Date: 2021-04-26 03:00
It's reproducible only if the float is nan, with prefix 7f or ff.
Seems the value is OR operated by 0x00400000.
msg391879 - (view) Author: Huang Yang (yang8621) Date: 2021-04-26 05:14
Also reproducible by:

from ctypes import *
i = int('7f94e57c', 16)
cp = pointer(c_int(i))
fp = cast(cp, POINTER(c_float))
print(fp.contents.value) # nan
p = pointer(c_float(fp.contents.value))
ip = cast(p, POINTER(c_int))
print(hex(ip.contents.value)) #'0x7fd4e57c'
msg391880 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2021-04-26 05:54
I believe that this may be the same issue as this thread

in particular this comment:
msg391883 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2021-04-26 07:40
There's an implicit float-to-double conversion here (`fp.contents.value` is represented as a Python float, which is backed by a C double). What you're seeing is that converting the single-precision signaling NaN to double precision loses the signaling bit, producing a quiet double-precision NaN with the same sign and payload (modulo the signaling bit). That's what I'd expect under IEEE 754 semantics. (IEEE 754-2008 says, in section 6.2, "Under default exception handling, any operation signaling an invalid operation exception and for which a floating-point result is to be delivered shall deliver a quiet NaN.".)

I don't think there's anything we can or should do about this at Python level. ctypes is correctly reflecting the existing C-level behaviour. In other words, this is expected behaviour, not a bug.
msg391884 - (view) Author: Huang Yang (yang8621) Date: 2021-04-26 08:38
OK. Seems it's the default behavior of CPU instruction. And CPU follows the IEEE standard of float. 

Is there any workaround?
msg391885 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2021-04-26 08:47
> Is there any workaround?

Sorry, I can't answer that without knowing what it is you're trying to do - that is, I don't know which part of the behaviour you want a workaround for. But that's getting off topic for this tracker, which is for bug reporting; I'd suggest taking the discussion to one of the mailing lists, Stack Overflow, or some other resource.
Date User Action Args
2022-04-11 14:59:44adminsetgithub: 88106
2021-04-26 08:47:06mark.dickinsonsetstatus: open -> closed

messages: + msg391885
stage: resolved
2021-04-26 08:38:26yang8621setstatus: pending -> open

messages: + msg391884
2021-04-26 08:15:19mark.dickinsonsetstatus: open -> pending
resolution: not a bug
2021-04-26 07:40:59mark.dickinsonsetmessages: + msg391883
2021-04-26 05:54:20steven.dapranosetnosy: + steven.daprano
messages: + msg391880
2021-04-26 05:14:27yang8621setmessages: + msg391879
2021-04-26 04:50:23rhettingersetnosy: + tim.peters, rhettinger, mark.dickinson
2021-04-26 03:00:01yang8621setmessages: + msg391877
2021-04-26 02:52:44yang8621create