将有序对(x,y)与无序对{x,y}(集合)进行比较,然后从理论上将信息相比较,差异仅是一位,因为x是第一个还是y都需要一个单独的位来表示。
因此,如果给定集合{x,y},其中x,y是两个不同的32位整数,是否可以将它们打包为63位(而不是64位)?应该可以从63位结果中恢复原始的32位整数,但不能恢复其顺序。
将有序对(x,y)与无序对{x,y}(集合)进行比较,然后从理论上将信息相比较,差异仅是一位,因为x是第一个还是y都需要一个单独的位来表示。
因此,如果给定集合{x,y},其中x,y是两个不同的32位整数,是否可以将它们打包为63位(而不是64位)?应该可以从63位结果中恢复原始的32位整数,但不能恢复其顺序。
Answers:
是的,可以。如果,则将集合映射到数字
很容易证明是双射的,因此可以对其进行唯一解码。此外,当,我们有,所以这个集合映射于63位的数字。为了解码,可以在使用二进制搜索,或采取平方根:应该大约。
x
和y
不同,则x-y-1
或y-x-1
(当然都是mod )都适合31位。如果较小,则串联和;的最后31位。否则串联,的最后31位。通过将前32位作为一个数字,再将前32位,后31位和常数1(模2 32)相加来恢复两个数字。x-y-1
y
x-y-1
x
y-x-1
个集合中无序数字对的总数为N (N + 1 )/ 2。无序对的总数量不同的数字是Ñ (ñ - 1 )/ 2。它需要2 日志2(Ñ )= 日志2(Ñ 2)比特来表示的有序对数的,并且如果有较少的位,则可以代表了一个空间的元件,以Ñ 2 / 2。无序的不必要对的数量略多于有序对的数量的一半,因此您无法在表示中节省一点;无序不重复对的数量略少于一半,因此您可以节省一点。
对于易于计算的实用方案(为2的幂),您可以进行按位表示。取一个= X ⊕ ÿ其中⊕是XOR(按位异或)运算符。所述一对{ X ,ÿ }可以从回收(一个,X )或(一,ÿ )。现在,我们将寻找技巧在第二部分中节省一位,并为x和y赋予对称角色因此无法恢复订单。给定以上基数计算,我们知道该方案在的情况下不起作用。
如果则存在一些不同的位位置。我会写X 我为我的第i比特X(即X = Σ 我X 我2 我),并且同样地对于ÿ。令k取x和y不同的最小位的位置:k是最小的i,以使x i ≠ y i。ķ是最小我使得一个我 =:我们可以恢复 ķ从一个。设 b为 x或 y,并删除第 k位(即 b = ∑ i < k x i 2 i + ∑ i > k x i 2 i − 1或 b = ∑ i < k y i 2 i + ∑ i > ķ ÿ 我2 我-) -使施工对称的,挑X如果 X ķ =0和 ÿ ķ =1,并挑选ÿ如果 X ķ =1和 ÿ ķ =0。使用(a,b)作为该对的紧凑表示。可以通过计算a中设置的最低位,在b中的该位置插入0位(产生x或y之一),然后使用该数字的xor来恢复原始对。(产生该对中的另一个元素)。
在此表示形式中,可以是任何非零数字,b可以是具有一半范围的任何数字。这是一个健全性检查:我们准确地获得了预期的无序对表示的数量。
在伪代码中,与^
,&
,|
,<<
,>>
,~
是C状位运算符(XOR,与,或,左移,右移,补体):
encode(x, y) =
let a = x ^ y
let k = lowest_set_bit_position(a)
let low_mask = (1 << k) - 1
let z = if x & (1 << k) = 0 then x else y
return (a, (z & low_mask) | (z & ~low_mask) >> 1)
decode(a, b) =
let k = lowest_set_bit_position(a)
let low_mask = (1 << k) - 1
let x = (b & low_mask) | ((b & ~low_mask) << 1)
return (x, a ^ x)