压缩两个整数,不考虑顺序


20

将有序对(x,y)与无序对{x,y}(集合)进行比较,然后从理论上将信息相比较,差异仅是一位,因为x是第一个还是y都需要一个单独的位来表示。

因此,如果给定集合{x,y},其中x,y是两个不同的32位整数,是否可以将它们打包为63位(而不是64位)?应该可以从63位结果中恢复原始的32位整数,但不能恢复其顺序。

Answers:


27

是的,可以。如果x<y,则将集合映射{x,y}到数字

f(x,y)=y(y1)/2+x.

很容易证明f是双射的,因此可以对其进行唯一解码。此外,当0x<y<232,我们有0f(x,y)<263231,所以这个集合映射{x,y}于63位的数字f(x,y)。为了解码,可以在使用二进制搜索y,或采取平方根:y应该大约2f(x,y)


1
就像1 + 2 + 3 + ... + y + x一样好!
Troy McClure's

1
归纳为n个无序整数?:)再三考虑,许多具有足够大的偏导数的四角形将完成这项工作
Troy McClure

4
另一个可能因其低计算成本而吸引人的答案:如果xy不同,则x-y-1y-x-1(当然都是mod )都适合31位。如果较小,则串联和;的最后31位。否则串联,的最后31位。通过将前32位作为一个数字,再将前32位,后31位和常数1(模2 32)相加来恢复两个数字。232x-y-1yx-y-1xy-x-1232
丹尼尔·瓦格纳

1
您的方法也可以很好地推广到添加更多的数字,因为第一个数字“就在那”可以链接
Troy McClure

4
@DW:您能否也补充一下如何提出这种表示形式?否则,似乎您是凭空抽出的。
Mehrdad

9

作为DW答案的补充,请注意,这是组合数系统的特殊情况,该系统紧凑地将非负整数c k > > c 1的严格递减序列映射为 N = k i = 1 c 一世kck>>c1

N=i=1k(cii).

这个数字有一个简单的解释。如果我们按字典顺序对这些序列进行排序,则计算较小序列的数量。N

要进行解码,只需为分配最大值,使得 c kck和解码ñ- çķ(ckk)Nk1序列。N(ckk)(k1)


4

个集合中无序数字对的总数为N N + 1 / 2。无序对的总数量不同的数字是Ñ ñ - 1 / 2。它需要2 日志2Ñ = 日志2Ñ 2比特来表示的有序对数的,并且如果有较少的位,则可以代表了一个空间的元件,以Ñ 2 / 2ñññ+1个/2ññ-1个/22日志2ñ=日志2ñ2ñ2/2。无序的不必要对的数量略多于有序对的数量的一半,因此您无法在表示中节省一点;无序不重复对的数量略少于一半,因此您可以节省一点。

对于易于计算的实用方案(为2的幂),您可以进行按位表示。取一个= X ÿ其中是XOR(按位异或)运算符。所述一对{ X ÿ }可以从回收一个X ÿ 。现在,我们将寻找技巧在第二部分中节省一位,并为xy赋予对称角色ñ一种=Xÿ{Xÿ}一种X一种ÿXÿ因此无法恢复订单。给定以上基数计算,我们知道该方案在的情况下不起作用。X=ÿ

如果则存在一些不同的位位置。我会写X 的第i比特X(即X = Σ X 2 ),并且同样地对于ÿ。令kxy不同的最小位的位置:k是最小的i,以使x iy iķ是最小使得一个 =XÿX一世一世XX=一世X一世2一世ÿķXÿķ一世X一世ÿ一世ķ一世:我们可以恢复 ķ一个。设 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 -一种一世=1个ķ一种bXÿķb=i<kxi2i+i>kxi2i1) -使施工对称的,挑X如果 X ķ =0 ÿ ķ =1,并挑选ÿ如果 X ķ =1 ÿ ķ =0。使用ab作为该对的紧凑表示。可以通过计算a中设置的最低位,在b中的该位置插入0位(产生xy之一),然后使用该数字的xor来恢复原始对。b=i<kyi2i+i>kyi2i1xxk=0yk=1yxk=1yk=0(a,b)abXÿ(产生该对中的另一个元素)。一种

在此表示形式中,可以是任何非零数字,b可以是具有一半范围的任何数字。这是一个健全性检查:我们准确地获得了预期的无序对表示的数量。一种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)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.