Android SQLiteDatabase - 存储和比较大数字

时间:2013-03-20 22:48:32

标签: android comparison largenumber sqlite

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

1 个答案:

答案 0 :(得分:1)

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

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

  

让编码的字节称为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数字而不是二进制值。 也就是说,使用带有 fixed 长度的前缀,该长度指定数字的长度,然后是数字。 假设您的号码不超过9999位,您可以使用前缀长度为4,例如:

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

如果您需要负值,则必须为正确排序的负数/正数选择一个额外的前缀(- / +的ASCII顺序错误,因此您最好使用某些东西比如n / p), 并且您必须使用 9999 - length 之类的前缀作为负数,以便较小的负数具有较小的前缀。