1

一个数字,如:

0.000000000000000000000000000000000000000123456

使用 postgres 中可用的数字类型,如果没有很大的性能损失,很难存储。这个问题解决了类似的问题,但我觉得它没有达到可接受的解决方案。目前,我的一位同事将这样的数字四舍五入到小数点后 15 位,并将它们存储为:

0.000000000000001

这样就可以使用双精度数字类型,这可以防止与移动到十进制数字类型相关的惩罚。就我的目的而言,这么小的数字在功能上或多或少是等效的,因为它们都非常小(并且意味着或多或少相同的东西)。然而,我们正在绘制这些结果,当大部分数据集像这样被四舍五入时,它看起来非常愚蠢(图表上的平线)。

在此处输入图像描述

因为我们要存储数万个这样的数字并对其进行操作,所以十进制数字类型对我们来说不是一个好的选择,因为性能损失太大。

我是一名科学家,我的自然倾向只是以科学计数法存储这些类型的数字,但 postgres 似乎没有这种功能。我实际上并不需要数字中的所有精度,我只想保留 4 位左右,所以我什至不需要 float 数字类型提供的 15 位。将这些数字存储在这样的两个字段中的优点和缺点是什么:

1.234 (real)
-40 (smallint)

这相当于 1.234*10^-40?这将允许大约 32000 个前导小数,只有 2 个字节用于存储它们,4 个字节用于存储实际值,每个数字总共最多 6 个字节(给我我想要存储的确切数字并且占用的空间比现有解决方案,消耗 8 个字节)。似乎对这些数字的排序也会得到很大改善,因为您只需要先对 smallint 字段进行排序,然后再对 real 字段进行排序。

4

2 回答 2

3

您和/或您的同事似乎对使用浮点格式可以表示哪些数字感到困惑。

一个double precision(又名float)数字可以存储至少 15 个有效数字,范围从大约 1e-307 到 1e+308。您必须将其视为科学记数法。删除所有零并将其移至指数。如果您在科学记数法中拥有的任何内容都少于 15 位,并且指数在 -307 和 +308 之间,则可以按原样存储。

这意味着0.000000000000000000000000000000000000000123456绝对可以将其存储为double precision,并且您将保留所有有效数字 ( 123456)。无需将其四舍五入0.000000000000001或类似的东西。

浮点数具有众所周知的十进制数的精确表示问题(因为以 10 为底的十进制数不一定映射到以 2 为底的十进制数),但这对您来说可能不是问题(如果您需要,这是一个问题)能够对这些数字进行精确比较)。

于 2016-02-07T23:12:37.583 回答
0

像这样将这些数字存储在两个字段中的优点和缺点是什么

您必须管理 2 列而不是 1 列。

粗略地说,您要做的是通过存储较低精度的浮点数来节省空间。如果您只需要 4 位精度,则可以使用 smallint + smallint (1000-9999 + exponent) 进一步节省 2 个字节。使用该格式,您可以将两个 smallint 塞进一个 32 位 int(指数 * 2 ^ 16 + 尾数),这也应该有效。

这是假设您需要节省存储空间和/或需要超出双精度浮点数的 +/-308 位指数限制。如果不是这种情况,则标准格式很好。

于 2016-02-07T23:02:29.110 回答