Ruby 两个整数的唯一对
可能重复:Ruby 两个整数的唯一对,ruby,database,crc32,Ruby,Database,Crc32,可能重复: 我正在尝试为两个整数对(Ruby)创建唯一标识符: 那么,i1+i2,i1*i2,i1^i2-不是唯一的,以及(i1>i2)?“i1”+“i2”:“i2”+“i1” 我认为以下解决方案可以: (i1>i2) ? "i1" + "_" + "i2" : "i2" + "_" + "i1" 但是: 我必须将结果保存在DB中并对其进行索引。所以我希望它是一个整数,并且尽可能小 crc32(f(i1,i2))能保证唯一性吗 谢谢 UPD: 实际上,我不确定结果一定是整数。也许我可以
我正在尝试为两个整数对(Ruby)创建唯一标识符: 那么,i1+i2,i1*i2,i1^i2-不是唯一的,以及(i1>i2)?“i1”+“i2”:“i2”+“i1” 我认为以下解决方案可以:
(i1>i2) ? "i1" + "_" + "i2" : "i2" + "_" + "i1"
但是:
?好吧,当4字节哈希的输入是一个超过4字节的任意二进制字符串时,它不会是唯一的。您的字符串来自高度受限的符号集,因此冲突将更少,但“不,不是唯一的” 有两种方法可以使用小于两个整数的可能值范围的整数:
Zlib.crc32(f(i1,i2))
对于i1和i2的所有整数值都不是唯一的
如果i1和i2也是32位数字,那么它们的组合比存储在32位数字(由CRC32返回)中的组合多得多。CRC32不是唯一的,不适合用作键。假设您知道整数的最大值
i1
和i2
:
unique_id = (max_i2+1)*i1 + i2
如果整数可以是负数,或者永远不会低于某个正整数,则需要最大值和最小值:
(max_i2-min_i2+1) * (i1-min_i1) + (i2-min_i2)
这将为您提供识别这两个整数的绝对最小数。您要查找的称为a 中的下图清楚地显示了其工作原理: 在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位数据类型才能存储所有可能的组合。)。我的回答哦,等等,我确实犯了一个小错误;更新代码最大值在我的例子中是一个Mysql BIGINT最大值。如果超过最大BIGINT值,我如何保存将在DB中获得的密钥?您是否有过BIGINT范围顶部的数字?如果是这样的话,你只需要使用一个字符串连接方法,比如“#{i1}{u35;{i2}”,因为没有办法对此进行优化。但是如果存在某种较小的最大范围,那么总有一种方法。那就是,你的值真的会达到9223372036854775807吗?九千五百万?如果他们只进入百万或低十亿,这个方法会起作用。我不认为我会达到最大的BIGINT,但我不知道我的最大值。所以可能带分隔符的字符串是最佳解决方案…正如我在其他答案中所评论的。。。这会生成太大的值,无法作为DB中的键。也许只是作为字符串离开(i1>i2)?“i1”+“+”i2:“i2”+“+”i1”是最佳值?添加到最大值将不起作用。它需要倍增。哦,是的。答案已更新。康托对(123123123123321321)=98765432098765778111444778111
a
和b
之间的鸿沟扩大时,康托函数获胜。但这是一个特殊的情况。我不认为一种方法对每一点都更好。但在一定范围内,比如说0到10000,铃木获胜。所以一般来说最好使用铃木函数。还要注意的是,铃木函数将结果打包在一个狭小的空间中,因为康托函数分布在一个大区域内。。
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]]