3

我有一个 10 字节(80 位)Little Endian 浮点值(或float80)的数组。我如何在 python 3 中读取这些值?

该软件包struct不支持float80(可能是我不小心阅读了文档)。

与“struct”包array相同的包不支持float80.

numpy支持float128float96类型。这非常好,但是附加\x00在尾部float80以将其扩展到float96或者很难看float128,导入这个包需要很多时间。

该软件包ctypes支持c_longdouble. 它比 numpy 快很多倍,但是sizeof(c_longdouble)依赖于机器并且可以少于 80 位,附加\x00在尾部float80以将其扩展到c_longdouble也很丑陋。

更新 1:在我的gist.github测试代码。该功能decode_str64很丑陋,但它确实有效。现在我正在寻找正确的方法

4

3 回答 3

3

让我以更合乎逻辑的方式重写我的答案:

ctypes c_longdouble是机器相关的,因为 longdouble 浮点类型不是由 C 标准一成不变的,而是依赖于编译器:(但它仍然是你现在可以拥有的最好的高精度浮点数......

如果您打算使用 numpy,那么 numpy.longdouble 就是您要寻找的,numpy.float96 或 numpy.float128 是高度误导的名称。它们不表示 96 位或 128 位 IEEE 浮点格式。相反,它们指示底层 long double 类型使用的对齐位数。因此,例如在 x86-32 上,long double 是 80 位,但被填充到 96 位以保持 32 位对齐,并且 numpy 调用它float96。在 x86-64 上,long double 再次是相同的 80 位类型,但现在它被填充到 128 位以保持 64 位对齐,并且 numpy 调用 this float128。没有额外的精度,只是额外的填充。

\x00在 a 的末尾附加float80以制作 aFloat96是丑陋的,但最终它只是 asfloat96只是一个填充的float80,并且numpy.longdouble是 afloat96float128取决于您使用的机器的体系结构。

numpy.float128 的内部精度是多少?

于 2016-08-09T12:02:43.600 回答
0

添加了填充,或者更确切地说,在 4 (x32) 或 16 (x64) 字节边界上的扩展精度浮点数的内存对齐 -由英特尔推荐- 以避免与处理非对齐数据相关的性能损失x86 CPU。为了让您了解点击量的大小,Microsoft 的一些数据显示 DWORD 的差异约为 2 倍。

这种布局根深蒂固于底层的 C 中,long double而不是numpy' 的发明,因此numpy不会尝试提供任何解决方法来仅提取/插入“重要”部分。

因此,如果您有没有填充的原始数据,则手动添加填充看起来像是要走的路。您可以通过直接写入底层缓冲区来加快该过程:

fi=np.finfo(np.longdouble)
assert fi.nmant==63 and fi.nexp==15, "80-bit float support is required"
del fi

len_float80=10    #no way to extract this from dtype/finfo
len_padded=np.dtype(np.longdouble).itemsize

f=open('float80.bin','rb')
f_items=os.stat(f.name).st_size//len_float80

n = np.empty(f_items,dtype=np.longdouble)

for i in xrange(f_items):
    raw=f.read(len_float80)
    n.data[i*len_padded:i*len_padded+len_float80]=raw

del f,i,raw,f_items

或者甚至通过将代码移植到 Cython 来获得更多的加速(如果使用原始缓冲区,与常规数组索引相比,加速可能高达 100 倍!这会损害代码的可维护性,但请注意此处的过早优化)。

或者,对于“交换”格式,您可以考虑使用不受内部表示形式约束的格式,例如savetxt.

于 2016-11-23T04:07:58.640 回答
0

numpy 如果编译器和平台支持它们,则可以使用 80 位浮点数

在 numpy 中是否可以[支持更高的精度]取决于硬件和开发环境:具体来说,x86 机器提供具有 80 位精度的硬件浮点,虽然大多数 C 编译器都将其作为其long double类型提供,但 MSVC(标准Windows 版本)long double与双精度(64 位)相同。Numpy 使编译器的 long double 可用作 np.longdouble(和 np.clongdouble 用于复数)。你可以找出你的 numpy 提供了什么np.finfo(np.longdouble)

我检查了PyPI 以及Gohlke 的构建和CentOS 6np.longdouble中的float64库存。numpy-1.11.1-win32.whlfloat96numpy-1.4.1-9.el6.i686

于 2016-09-30T07:20:46.470 回答