可能重复:
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"
但:
感谢。
UPD:
实际上,我不确定结果必须是整数。也许我可以把它转换成十进制: (i1> i2)? i1.i2:i2.i1
答案 0 :(得分:6)
您要找的是Pairing function。
German wikipedia page中的以下插图清楚地显示了它的工作原理:
在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:1映射解决问题的明显方法要求您知道其中一个整数的最大值。只需将一个乘以最大值并加上另一个,或确定两个上限的幂,相应地移动一个值,然后在另一个中移动OR。无论哪种方式,每个位都保留用于整数中的一个或另一个。这可能会或可能不会满足您“尽可能小”的要求。
你的### _ ###字符串每对都是唯一的;如果你能把它作为一个字符串存储就赢了。
答案 3 :(得分:1)
CRC32不是唯一的,并且不适合用作密钥。假设您知道整数i1
和i2
的最大值:
unique_id = (max_i2+1)*i1 + i2
如果你的整数可以是负数,或者永远不会低于某个正整数,那么你需要最大值和最小值:
(max_i2-min_i2+1) * (i1-min_i1) + (i2-min_i2)
这将为您提供识别两个整数的绝对最小数。
答案 4 :(得分:0)