C(C89)中十进制数的高效磁盘存储

C(C89)中十进制数的高效磁盘存储,c,serialization,floating-point,storage,disk,C,Serialization,Floating Point,Storage,Disk,我正在编写序列化/反序列化大型数据结构的函数,以便以后高效地重新加载。有一组特定的十进制数,精度不是很大,我想将它们存储在4字节的二进制数据中 对于大多数情况,将字节读入缓冲区并使用memcpy将它们放入浮点就足够了,这是我发现的最常见的解决方案。但是,这是不可移植的,因为该软件用于的系统上的浮动不能保证大小为4字节 我想要的是非常便携的东西(这也是我限制使用C89的原因之一)。我并不热衷于4字节存储,但它对我来说是一个很有吸引力的选择。我完全反对将数字存储为字符串。我熟悉endianness问

我正在编写序列化/反序列化大型数据结构的函数,以便以后高效地重新加载。有一组特定的十进制数,精度不是很大,我想将它们存储在4字节的二进制数据中

对于大多数情况,将字节读入缓冲区并使用memcpy将它们放入浮点就足够了,这是我发现的最常见的解决方案。但是,这是不可移植的,因为该软件用于的系统上的浮动不能保证大小为4字节

我想要的是非常便携的东西(这也是我限制使用C89的原因之一)。我并不热衷于4字节存储,但它对我来说是一个很有吸引力的选择。我完全反对将数字存储为字符串。我熟悉endianness问题,这些问题已经考虑在内了


因此,我要寻找的是一种独立于系统的方法,用少量二进制数据(最好是4字节左右)存储和检索浮点数。一、 我愚蠢地认为这是这项任务中最简单的部分,因为这似乎是一个常见的问题,但流行的搜索引擎和各种参考书都没有提供实质性的帮助。

你可以将它们存储在32位IEEE浮点格式中(或者与之非常接近,例如,您可能需要限制什么去噪和去噪)。然后让每个平台根据需要进行调整,以强制其自己的
float
类型使用该格式并返回

当然会有一些精度的损失,但是如果你将不同精度的浮点值从一个系统转移到另一个系统,这是不可避免的

如果需要的话,应该可以编写可移植代码来查找与本机
浮点值最接近的IEEE值,反之亦然。不过,您不会真的想使用它,因为它可能比利用了解
浮点格式的代码效率低得多。在通常情况下atform使用IEEE表示法,它是一种无运算或简单的缩小/扩大转换。即使在最坏的情况下,您可能会遇到,只要它是一个二进制分数,您基本上只需提取符号、指数和有效位,并对其进行正确处理(如果有效位太大,则丢弃有效位中的位,调整偏差,并可能调整指数的宽度,对下溢和上溢进行正确处理)

如果您想避免在保存文件然后在同一系统上重新加载(但该系统不使用32位IEEE)的情况下丢失准确性,您可以考虑在文件中存储一些指示格式的数据(每个值的大小、有效位和指数的位数),然后以本机精度存储每个值,这样只有当它加载到精度较低的系统上时,它才会被舍入。我不知道ASN.1是否有一个标准来沿这些线编码浮点值,但这是我所期望的一种复杂的诡计。

查看以下内容:


它们提供了一个可移植且不会增加太多开销的例程。

您的平台到底支持什么?IEEE浮点值有保证吗?您是否担心只有16位浮点值或64位浮点值可用?数据是否必须在写入数据的机器以外的机器上读取?如果没有,则使用教科书解决方案可以使用直接二进制文件
write()
fwrite()写入数据
然后重新阅读。在阅读之前,你需要知道你正在阅读的内容,但文件结构可能会告诉你这一点。如果你的数据需要可移动,那么你面前的任务就更艰巨了,Steve Jessop的解决方案是合理的。值的范围是什么?它会使用全指数范围还是全指数范围在C89中,通常不保证IEEE浮点数是有限的子集(例如±1000000,不超过6位?)。几乎可以肯定的是,我必须处理的是IEEE,4(8位)字节浮动,事实上,文件很可能只由编写它们的系统读取。目前,这是一个部分学术问题,因为我惊讶地发现这是一项多么麻烦的任务。当然,这意味着我必须投入所有的麻烦,并在所有情况下找到解决方案。