Mengompresi dua bilangan bulat dengan mengabaikan pesanan


20

Membandingkan pasangan berurutan (x, y) dengan pasangan yang tidak berurutan {x, y} (set), maka informasi secara teoritis, perbedaannya hanya satu bit, karena apakah x lebih dulu atau y membutuhkan tepat satu bit untuk diwakili.

Jadi, jika kita diberikan satu set {x, y} di mana x, y adalah dua bilangan bulat 32-bit yang berbeda, dapatkah kita mengemasnya menjadi 63 bit (bukan 64)? Seharusnya dimungkinkan untuk memulihkan bilangan bulat 32 bit asli dari hasil 63 bit, tetapi tanpa dapat memulihkan pesanan mereka.

Jawaban:


27

Ya, bisa. Jika , petakan set ke nomor tersebutx<y{x,y}

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

Mudah untuk menunjukkan bahwa adalah kata sifat, dan dengan demikian ini dapat diterjemahkan secara unik. Juga, ketika , kita memiliki , jadi ini memetakan set ke nomor 63-bit . Untuk memecahkan kode, Anda dapat menggunakan pencarian biner pada , atau mengambil akar kuadrat: harus kira-kira .f0x<y<2320f(x,y)<263231{x,y}f(x,y)yy2f(x,y)


1
sama seperti 1 + 2 + 3 + ... + y + x bagus!
Troy McClure

1
ada generalisasi untuk n unordered ints? :) setelah dipikir-pikir, banyak quadform dengan turunan parsial yang cukup besar akan melakukan pekerjaan itu
Troy McClure

4
Jawaban lain yang mungkin menarik karena biaya komputasinya yang rendah: jika xdan yberbeda, maka salah satu x-y-1atau y-x-1(keduanya mod , tentu saja) cocok dalam 31 bit. Jika kecil, maka gabungkan dan 31 bit terakhir ; jika tidak digabungkan dan 31 bit terakhir dari . Pulihkan kedua angka dengan mengambil 32 bit pertama sebagai satu angka dan menambahkan 32 bit pertama, 31 bit terakhir, dan konstanta 1 (mod ) sebagai yang lainnya. 2 32232x-y-1yx-y-1xy-x-1232
Daniel Wagner

1
metode Anda juga menggeneralisasi dengan baik untuk menambahkan lebih banyak angka, karena angka pertama adalah "hanya di sana" sehingga dapat berantai
Troy McClure

4
@DW: Bisakah Anda juga menambahkan bagaimana Anda membuat representasi ini? Kalau tidak, sepertinya Anda menariknya keluar dari udara tipis.
Mehrdad

9

Sebagai tambahan untuk jawaban DW, perhatikan bahwa ini adalah kasus khusus dari Combinatorial Number System , yang memetakan secara ketat urutan bilangan bulat non-negatif ke c k > > c 1 N = k i = 1 ( c ikck>>c1

N=i=1k(cii).

Angka ini memiliki interpretasi sederhana. Jika kita memesan urutan ini secara leksikografis, maka menghitung jumlah urutan yang lebih kecil.N

Untuk mendekode, cukup berikan nilai terbesar sehingga dan dekode sebagai -setelahnya.( c kckN- ( ck(ckk)N (k-1)N(ckk)(k1)


4

Jumlah total pasangan angka yang tidak berurutan dalam satu set adalah . Jumlah pasangan unordered dari yang berbeda angka adalah . Dibutuhkan bit untuk mewakili pasangan angka yang terurut, dan jika Anda memiliki lebih sedikit, Anda dapat mewakili elemen ruang hingga . Jumlah pasangan tidak-tidak-harus-tidak berurutan sedikit lebih dari setengah jumlah pasangan yang dipesan sehingga Anda tidak dapat menyimpan sedikit dalam representasi; jumlah pasangan berbeda yang tidak berurutan sedikit kurang dari setengah, sehingga Anda dapat menghemat sedikit.NN(N+1)/2N(N1)/22log2(N)=log2(N2)N2/2

Untuk skema praktis yang mudah dihitung, dengan menjadi kekuatan 2, Anda bisa bekerja pada representasi bitwise. Ambil mana adalah XOR (bitwise eksklusif atau). Pasangan dapat dipulihkan dari atau . Sekarang kita akan mencari trik untuk menyimpan satu bit di bagian kedua, dan memberikan peran simetris ke dan sehingga pesanan tidak dapat dipulihkan. Dengan perhitungan kardinalitas di atas, kami tahu skema ini tidak akan berfungsi jika .Na=xy{x,y}(a,x)(a,y)xyx=y

Jika maka ada beberapa posisi bit di mana mereka berbeda. Saya akan menulis untuk bit ke- (yaitu ), dan juga untuk . Biarkan mengambil posisi bit terkecil di mana dan berbeda: adalah terkecil sehingga . adalah terkecil sehingga : kita dapat memulihkan dari . Biarkan menjadi ataux ixyxiixx=ixi2iykxykixiyikiai=1kabxydengan bit dihapus (yaitu atau ) - untuk membuat simetris konstruksi, pilih jika dan , dan pilih jika dan . Gunakan sebagai representasi kompak dari pasangan. Pasangan asli dapat dipulihkan dengan menghitung bit urutan terendah yang diatur dalam , memasukkan 0 bit pada posisi ini dalam (menghasilkan salah satu atau ), dan mengambil xor dari angka itu dengankb=i<kxi2i+i>kxi2i1b=i<kyi2i+i>kyi2i1xxk=0yk=1yxk=1yk=0(a,b)abxya (menghasilkan elemen pasangan lainnya).

Dalam representasi ini, bisa berupa bilangan bukan nol, dan dapat berupa bilangan apa saja dengan setengah kisaran. Ini adalah pemeriksaan kewarasan: kami mendapatkan persis jumlah yang diharapkan dari representasi pasangan tidak berurutan.ab

Dalam pseudocode, dengan ^, &, |, <<, >>, ~menjadi C-seperti operator bitwise (xor, dan, atau, kiri-shift, kanan-shift, pelengkap):

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)

0

Bukti nonkonstruktif: ada tidak berurutan pasang bilangan bulat 32-bit yang berbeda.(232×232232)/2=231(2321)<263

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.