如何以定义明确的非自定义格式编写小数

问题描述

假设我有一个传感器返回测量数据(例如每秒 6 x 50 个值)。每个值都是单精度浮点数范围内的小数。我需要将这些数据写入一个文件,然后由另一个应用程序读取该文件以进行其他操作。格式化/编码文件的最有效方法是什么?

起初我认为 CSV 是为了简单起见,但后来使用科学记数法会导致每个十进制长度为 9 个字节或更多(例如 -4,97E-03)。在大量传感器上长时间保留数据的情况下,这可能是存储约束的问题,也因为这些数据具有高熵,因此压缩没有太大帮助。

所以我在考虑将小数保存为浮点数(4 个字节)会节省大量数据,但我不知道哪些格式提供了用于存储浮点数表的明确定义的结构。是否有类似逗号分隔值的东西,其中值是 IEEE754 格式,或者类似的东西?我问这个是因为我想避免定义自定义格式。

解决方法

正如您所说,以人类可读的文本格式(如 CSV)编码浮点数在空间上效率很低,因为每个 32 位浮点数需要花费十几个字符来编码。作为测试,我生成了 100 万个随机 32 位浮点数并将它们保存为文本文件:

-5.92667373e+04
-1.10473797e+05
7.58996562e+04
3.52729886e+04
...

此文件的大小为 15,499,059 字节。 但是,这样的文本文件压缩得很好! 通过gzip 运行文件后,文件大小减少到5,925,628 字节。这还不错,大约是将浮点数存储为二进制数据(4,000,000 字节)的成本的 1.5 倍。

32 位浮点数表示大约 7 位有效数字的精度,但这对于表示测量值来说可能过多,尤其是在已知测量值比这更不精确的情况下。使用文本格式,您可以通过打印较少的有效数字来节省空间。或者,如果写入二进制数据,您可以通过舍入为 16-bit half-precision floats 或 16 位 fixed-point representation 将成本降低一半。

正如 Eric 评论的那样,您可以直接编写原始二进制数据,连同数组维度或其他任何您需要的内容,并提出您自己的临时格式。但如果您更愿意使用现有的标准格式,这里有一些建议:

  • NPY format 由 Python numpy 库本地支持,可以表示浮点数数组或几乎可以放入 numpy 数组的任何其他内容。如果您已经在使用 Python,那么可以使用 np.loadnp.save 轻松读取和写入 NPY 文件。其他语言中也有 NPY 的实现,例如 C++ 中的 https://github.com/rogersce/cnpy 和 Rust 中的 https://docs.rs/npy/0.4.0/npy

  • FITS format 在天文学中被广泛使用。 FITS 使用简单的二进制编码存储任意大小和维数的浮点数据数组,并且可以在文本头字段中存储任意元数据。格式有意简单,因此实现您自己的读取器和写入器相对简单。