3

我正在尝试存储一个非常大的数字,该数字大于 INTEGER 和 REAL 字段类型可以容纳的 8 个字节。我需要能够返回包含此字段中的数字的行,该数字小于或大于我指定的另一个大数字。我不知道该怎么做。似乎我唯一的选择是将其存储为 TEXT,但是当我尝试在查询中使用 > 和 < 进行比较时遇到问题,因为 TEXT 的比较与数字比较不同(当数字的位数不同)。我尝试过使用 BLOB 或将我的大数存储为字节数组,但无济于事。用零填充数字以使它们具有相同的位数也不起作用,因为我不知道数字可能有多大。任何帮助表示赞赏。谢谢!

4

1 回答 1

1

对于存储,您唯一的选择是 TEXT 或 BLOB,因此您必须以某种方式对数字进行编码,以便字典顺序和数字顺序相同。

对于无符号数,您可以使用类似于 SQLite4 的varintencoding的机制:

让编码的字节被称为 A0, A1, A2, ..., A8。
如果 A0 介于 0 和 240(含)之间,则结果为 A0 的值。
如果 A0 介于 241 和 248 之间,则结果为 240+256*(A0-241)+A1。
如果 A0 为 249,则结果为 2287+256*A1+A2。
如果 A0 为 250,则结果为 A1..A3 作为 3 字节大端整数。
如果 A0 为 251,则结果为 A1..A4 作为 4 字节大端整数。
如果 A0 为 252,则结果为 A1..A5 作为 5 字节大端整数。
如果 A0 为 253,则结果为 A1..A6 作为 6 字节大端整数。
如果 A0 为 254,则结果为 A1..A7 作为 7 字节大端整数。
如果 A0 为 255,则结果为 A1..A8 作为 8 字节大端整数。

以上是为最多 64 位数字设计的。只要你有一个上限,为更大的数字扩展机制是微不足道

如果数字可以签名,则必须将A0范围分成两半,并将前半部分用于负数。

如果您不需要进行计算,您可以使用相同的原则来存储 ASCII 数字而不是二进制值。也就是说,使用具有固定长度的前缀来指定数字的长度,然后是数字。假设您的号码不超过 9999 位,您可以使用四个前缀长度,例如:

0001|0  ...
0001|9
0002|10  ...
0002|99
0003|100  ...
0060|321741185926535897932384626433832795281828459045235360287471

如果这里需要负值,则必须为正确排序的负数/正数选择一个附加前缀( / 的 ASCII 顺序-+错误的,所以最好使用n/之类的东西p),并且必须使用9999 之类的前缀 -负数的长度,以便较小的负数具有较小的前缀。

于 2013-03-21T07:44:44.943 回答