独特的两个整数对

时间:2012-12-13 19:59:47

标签: ruby database crc32

  

可能重复:
  Mapping two integers to one, in a unique and deterministic way

我正在尝试为两个整数(Ruby)创建唯一标识符:

f(i1,i2) = f(i2, i1) = some_unique_value

那么,i1 + i2,i1 * i2,i1 ^ i2-不唯一以及(i1> i2)? “i1”+“i2”:“i2”+“i1”。

我认为以下解决方案可以:

(i1>i2) ? "i1" + "_" + "i2" : "i2" + "_" + "i1"

但:

  1. 我必须将结果保存在DB中并将其编入索引。所以我更喜欢它是一个整数,尽可能小。
  2. Zlib.crc32(f(i1,i2))是否可以保证唯一性?
  3. 感谢。

    UPD:

    实际上,我不确定结果必须是整数。也许我可以把它转换成十进制: (i1> i2)? i1.i2:i2.i1

5 个答案:

答案 0 :(得分:6)

您要找的是Pairing function

German wikipedia page中的以下插图清楚地显示了它的工作原理:

http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Pairing-function.svg/350px-Pairing-function.svg.png

在Ruby中实现:

def cantor_pairing(n, m)
    (n + m) * (n + m + 1) / 2 + m
end

(0..5).map do |n|
  (0..5).map do |m|
    cantor_pairing(n, m)
  end
end
=> [[ 0,  2,  5,  9, 14, 20],
    [ 1,  4,  8, 13, 19, 26],
    [ 3,  7, 12, 18, 25, 33],
    [ 6, 11, 17, 24, 32, 41],
    [10, 16, 23, 31, 40, 50],
    [15, 22, 30, 39, 49, 60]]

请注意,您需要将此配对的结果存储在数据类型中,该数据类型的位数与输入数字放在一起的位数一样多。 (如果两个输入数字都是32位,那么显然需要一个64位数据类型才能存储所有可能的组合。)

答案 1 :(得分:2)

不,Zlib.crc32(f(i1,i2))对于i1和i2的所有整数值都不是唯一的。

如果i1和i2也是32位数字,那么它们的组合会比存储在32位数字中的组合多得多,后者由CRC32返回。

答案 2 :(得分:1)

当其输入是超过4个字节的任意二进制字符串时,没有4字节散列是唯一的。您的字符串来自高度受限制的符号集,因此冲突会更少,但“不,不唯一”。

对于两个整数,有两种方法可以使用小于整数值的小整数:

  1. 尽管偶尔发生碰撞,但系统仍能正常工作
  2. 检查冲突并使用某种重新连接
  3. 使用1:1映射解决问题的明显方法要求您知道其中一个整数的最大值。只需将一个乘以最大值并加上另一个,或确定两个上限的幂,相应地移动一个值,然后在另一个中移动OR。无论哪种方式,每个位都保留用于整数中的一个或另一个。这可能会或可能不会满足您“尽可能小”的要求。

    你的### _ ###字符串每对都是唯一的;如果你能把它作为一个字符串存储就赢了。

答案 3 :(得分:1)

CRC32不是唯一的,并且不适合用作密钥。假设您知道整数i1i2的最大值:

unique_id = (max_i2+1)*i1 + i2

如果你的整数可以是负数,或者永远不会低于某个正整数,那么你需要最大值和最小值:

(max_i2-min_i2+1) * (i1-min_i1) + (i2-min_i2)

这将为您提供识别两个整数的绝对最小数。

答案 4 :(得分:0)