python - 如何在不设置第 23 位的情况下在 python 中创建自定义 NaN(单精度)?

标签 python struct ctypes nan floating-point-conversion

我正在尝试通过选择分数 位来创建浮点 NaN。但似乎 python float 在解释 NaN 时总是设置第 23 个小数位(IEEE754 单)。

所以,我的问题是:是否可以在不设置第 23 位的情况下在 python 中定义 float nan?

(我使用的是 Python 2.7)

NaNs in IEEE 754 have this format:
sign = either 0 or 1.
biased exponent = all 1 bits.
fraction = anything except all 0 bits (since all 0 bits represents infinity).

因此,NaN 的十六进制表示可能是 0x7F800001,但是当将此 int 解释为 float 并将其解释回 int 时,会得到 0x7FC00001

第一次尝试:struct.pack/unpack:

import struct

def hex_to_float(value):
    return struct.unpack( '@f', struct.pack( '@L', value) )[0]

def float_to_hex(value):
    return struct.unpack( '@L', struct.pack( '@f', value) )[0]

print hex(float_to_hex(hex_to_float(0x7f800001)))
# 0x7fc00001

第二次尝试:ctypes

import ctypes

def float2hex(float_input):
    INTP = ctypes.POINTER(ctypes.c_uint)
    float_value = ctypes.c_float(float_input)
    my_pointer = ctypes.cast(ctypes.addressof(float_value), INTP)
    return my_pointer.contents.value

def hex2float(hex_input):
    FLOATP = ctypes.POINTER(ctypes.c_float)
    int_value = ctypes.c_uint(hex_input)
    my_pointer = ctypes.cast(ctypes.addressof(int_value), FLOATP)
    return my_pointer.contents.value

print hex(float2hex(hex2float(0x7f800001)))
# 0x7fc00001L

第三次尝试:xdrlib packers。相同的结果。

最佳答案

潜在的问题是您将 C-float(具有 32 位)转换为 Python-float(具有 64 位,即 C 语言中的 double),然后再转换回 C-float .

两个 cconversions 的执行并不总是导致原始输入 - 你正在目睹这种情况。

如果确切的位模式很重要,您应该不惜一切代价避免上述转换。


这里有一些血淋淋的细节:

所以当 struct.unpack('=f', some_bytes)(请注意,与您使用的相比,我使用标准大小的 =-format 字符 native 大小 ('@'),例如 @L 在 Windows 和 Linux 上表示不同的东西),会发生以下情况:

在 x86-64 上,最后一次转换意味着操作 VCVTSS2SD (即将标量单精度浮点值转换为标量 double 浮点值)并且此操作导致

0x7f800001 变成 0x7ff8000020000000

如您所见,操作 struct.unpack( '=f', struct.pack( '=L', value) )[0] 的结果已经不是放入的结果.

但是,为 python-float value(它是 C 的 double), 将使我们到达 _PyFloat_Pack4 , wheredoublefloat 的转换发生了,即 CVTSD2SS (Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value) 被调用并且

0x7ff8000020000000 变为 0x7fc00001

关于python - 如何在不设置第 23 位的情况下在 python 中创建自定义 NaN(单精度)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56298877/

相关文章:

python - 如果Python中的单元格包含特定字符,如何为其着色?

python - 如何在 python 中用数据框中的随机整数替换 0?

python - 编辑 Ctypes 结构的缓冲区

C++ 结构初始化

json - 来自 json 的嵌套结构,解析为结构

python - 返回与指针赋值之间的 c_char_p 行为不一致

python - 我无法使用 ctypes cuda 获得输出数字

python 多个字典比较

python - 如何在Python 3中的集合中的特定位置/索引中添加值?

c++ - C中的 "union"和 "struct"之间的主要区别是什么?