2

我正在使用 Numpy 和 Python。我需要复制数据,没有 np.uint64 和 np.float64 之间的数字转换,例如1.5 <-> 0x3ff8000000000000

我知道 float.hex,但输出格式与 uint64 相差甚远:

In [30]: a=1.5
In [31]: float.hex(a)
Out[31]: '0x1.8000000000000p+0'

我也知道其他方式的各种字符串输入例程。

有人可以建议更直接的方法吗?毕竟,它只是简单的复制和类型更改,但 python/numpy 在转换数据的过程中似乎非常严格。

4

2 回答 2

2

使用中间数组和将frombuffer一种数组类型“转换”到另一种数组类型的方法:

>>> v = 1.5
>>> fa = np.array([v], dtype='float64')
>>> ua = np.frombuffer(fa, dtype='uint64')
>>> ua[0]
4609434218613702656      # 0x3ff8000000000000

由于frombuffer在原始缓冲区中创建了一个视图,因此即使重新解释大型数组中的数据也是有效的。

于 2014-07-09T06:16:15.043 回答
1

因此,您需要将内存中表示 float64 的 8 个字节视为整数。(将这个 int64 数字表示为十六进制字符串是另一回事 - 它只是它的表示形式)。

与 stdlib 的 ctypes 捆绑在一起的 Struct 和 Union 功能可能对您很好 - 不需要 numpy. 它有一个 Union 类型,其工作方式与 C 语言联合非常相似,并允许您执行以下操作:

>>> import ctypes
>>> class Conv(ctypes.Union):
...   _fields_ = [ ("float", ctypes.c_double), ("int", ctypes.c_uint64)]
... 
>>> c = Conv()
>>> c.float = 1.5
>>> print hex(c.int)
0x3ff8000000000000L

内置的“hex”函数是一种获取数字的十六进制表示的方法。

您也可以使用该struct模块:将数字打包为双精度字符串,然后将其解压缩为 int。我认为它的可读性和效率都比使用 ctypes Union 低:

>>> inport struct
>>> hex(struct.unpack("<Q",  struct.pack("<d", 1.5))[0])
'0x3ff8000000000000'

但是,由于您使用的是 numpy ,因此您可以简单地“即时”更改数组类型,并将所有数组作为具有 0 副本的整数进行操作:

>>> import numpy
>>> x = numpy.array((1.5,), dtype=numpy.double)
>>> x[0]
1.5
>>> x.dtype=numpy.dtype("uint64")
>>> x[0]
4609434218613702656
>>> hex(x[0])
'0x3ff8000000000000L'

这是迄今为止最有效的方法,无论您获取 float64 数字的原始字节的目的是什么。

于 2014-07-09T06:04:09.577 回答