浮点的替代方法,用于存储简单的小数值

An Alternative to Floating-Point for Storing Simple Fractional Values

本文关键字:存储 简单 小数 用于 方法      更新时间:2023-10-16

首先,我试图解决的问题是为始终在范围内均匀分布的值提出更好的表示:

0.0 <= x < 1.0

这样做的动机是尝试减少用于存储此数据的字节数(应用程序内存和 I/O 带宽受到严重限制)。目前使用的是 32 位浮点表示,16 位浮点表示被证明不够准确。

我最初的想法是尝试将数据存储在 16 位整数中,并简单地使用该方案:

x/(2^16 - 1) [x is an unsigned short]

为了保持算法基本相同并保留使用相同的浮点硬件操作(至少一开始),理想情况下,我希望继续将此分数表示转换为浮点表示,执行操作,然后转换回分数表示以进行存储。

显然,在

这两种完全不同的、不精确的表示之间来回会损失精度,但对于我们的应用程序,我怀疑这可能是一个可以接受的权衡。

我已经做了一些研究,看看目前的情况可能会给我们一个很好的起点。开创性的"每个计算机科学家都应该知道的关于浮点算术"的文章(http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)让我看了其他一些,"超越浮点"(home.ccil.org/~cowan/temp/p319-clenshaw.pdf)就是这样一个例子。

谁能指出人们在其他地方使用的其他可能满足这些要求的表示示例?

我担心表示准确性的任何潜在收益(我们目前使用这个特定范围浪费了大部分浮点格式)将被从分数表示到浮点表示两次并再次舍入的要求完全抵消。在这种情况下,可能需要直接使用这种分数表示进行算术,以便从这种方法中获得任何好处。关于这一点的任何建议会有所帮助吗?

不要使用 2^16-1 .使用2^16 .是的,您的精度会略低并浪费您的0xFFFF,但您将保证在转换为浮点数时精度不会损失。(相反,当从浮点转换时,您将失去 8 位尾数精度。

精度之间的往返转换可能会导致某些运算出现问题,尤其是渐进式求和数字时。如果可能的话,将定点值视为"脏",不要将它们用于进一步的浮点计算;更喜欢从输入重新计算,而不是使用定点形式的中间结果。

或者,使用 24 位。使用此表示形式,只要您的值不下溢(即,只要它们高于 2^-24),您就不会在任一方向上丢失精度。

1/x 在您的范围内分布不均匀吗? 1/2 1/3 1/4 ..你不想表示 1/2 以上的数字吗?

这种事情在Netcdf中做了很多事情来编码数据以节省空间。

const double scale = 1.0/65536;
unsigned short x;
x

中的任何数字实际上都是 x*scale

有关使用缩放和偏移的更常规方法,请参阅 NetCDF 中的示例:http://www.unidata.ucar.edu/software/thredds/current/netcdf-java/tutorial/NetcdfDataset.html

请查看本页的"打包数据值"部分:

https://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#Packed%20Data%20Values