我有一个10字节(80位)Little Endian浮点值(或struct
)的数组。我怎样才能在python 3中读取这个值?
包float80
不支持array
(可能是我不小心阅读了文档)。
包float80
与包" struct"相同不支持numpy
。
包float128
支持float96
或\x00
类型。它非常好,但将float80
添加到float96
的尾部以将其扩展为float128
或ctypes
是丑陋的,导入此软件包需要花费很多时间。
包c_longdouble
支持sizeof(c_longdouble)
。它比numpy快很多倍,但\x00
与机器有关,可能小于80位,在float80
的尾部附加c_longdouble
以将其扩展为{{ 1}}也很难看。
更新1 :在gist.github处测试代码。
函数decode_str64
很难看,但它有效。现在我正在寻找正确的方式
答案 0 :(得分:2)
让我以更合乎逻辑的方式重写我的答案:
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调用此float128
。没有额外的精度,只是额外的填充。
在\x00
末尾添加float80
以使Float96
变得丑陋,但最后只是因为float96
只是填充float80
1}}和numpy.longdouble
是float96
或float128
,具体取决于您使用的机器的体系结构。
答案 1 :(得分:0)
numpy
can use 80-bit float if the compiler and platform support them:
numpy中是否可以[支持更高精度]取决于 硬件和开发环境:特别是x86 机器提供80位精度的硬件浮点数 而大多数C编译器都将其作为
long double
类型,MSVC (Windows版本的标准)使long double
与double相同 (64位)。 Numpy使编译器的long double可用np.longdouble
(和复数的np.clongdouble)。您可以 找出你的numpy为np.finfo(np.longdouble)
提供的内容。
我在PyPI以及np.longdouble
中的float64
和numpy-1.11.1-win32.whl
中检查了float96
numpy-1.4.1-9.el6.i686
库存post
是否为pre
答案 2 :(得分:0)
在4(x32)或16(x64)字节边界上添加填充或更确切地说,扩展精度浮点的内存对齐 - by recommendatation from Intel no less - 以避免与处理非对齐相关的性能损失x86 CPU上的数据。为了让您了解命中数量some figures from Microsoft show ~2 times difference for DWORDs.
This layout is ingrained into the underlying C's long double
而不是numpy
的发明,因此numpy
并未尝试提供任何方法来提取/插入&#34 ;显著"一部分。
因此,如果你有没有填充的原始数据,手动添加填充看起来就像是要走的路。您可以通过直接写入底层缓冲区来加快进程:
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
甚至可以通过porting the code to Cython获得更多的加速(if using raw buffers, the speedup compared to regular array indexing can be as much as 100x!这会损害代码的可维护性,但请注意这里的过早优化。)
或者,对于"交换"格式,您可以考虑使用未绑定到内部表示的格式,例如savetxt
。