Comprimere due numeri interi ignorando l'ordine


20

Confrontando una coppia ordinata (x, y) con una coppia non ordinata {x, y} (set), quindi le informazioni teoricamente, la differenza è solo un bit, come se x viene prima o y richiede esattamente un singolo bit per rappresentare.

Quindi, se ci viene dato un set {x, y} in cui x, y sono due diversi numeri interi a 32 bit, possiamo comprimerli in 63 bit (piuttosto 64)? Dovrebbe essere possibile ripristinare gli interi originali a 32 bit dal risultato a 63 bit, ma senza poter recuperare il loro ordine.

Risposte:


27

Sì, uno può. Se x<y , associa il set {x,y} al numero

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

È facile dimostrare che f è biiettivo e quindi può essere decodificato in modo univoco. Inoltre, quando 0x<y<232 , abbiamo 0f(x,y)<263231 , quindi questo mappa l'insieme {x,y} su un numero a 63 bit f(x,y) . Per decodificare, puoi usare la ricerca binaria su y o prendere una radice quadrata: y dovrebbe essere approssimativamente .2f(x,y)


1
proprio come 1 + 2 + 3 + ... + y + x bello!
Troy McClure,

1
qualsiasi generalizzazione in n non ordinati? :) ripensandoci, molti quadform con derivati ​​parziali abbastanza grandi faranno il loro lavoro
Troy McClure,

4
Un'altra risposta che può essere interessante per il suo basso costo di calcolo: se xe ysono diversi, allora uno x-y-1o y-x-1entrambi (entrambi mod , ovviamente) si inserisce in 31 bit. Se è piccolo, concatenare e gli ultimi 31 bit di ; altrimenti concatenare e gli ultimi 31 bit di . Recupera i due numeri prendendo i primi 32 bit come un numero e aggiungendo i primi 32 bit, gli ultimi 31 bit e la costante 1 (mod 2 32 ) come l'altro. 232x-y-1yx-y-1xy-x-1232
Daniel Wagner,

1
il tuo metodo si generalizza anche bene aggiungendo più numeri, poiché il primo numero è "proprio lì", quindi può incatenarsi
Troy McClure,

4
@DW: Potresti aggiungere anche come hai realizzato questa rappresentazione? Altrimenti sembra che tu l'abbia tirato fuori dal nulla.
Mehrdad,

9

In aggiunta alla risposta di DW, nota che questo è un caso particolare del Combinatorial Number System , che mappa in modo compatto una sequenza strettamente decrescente di numeri interi non negativi c k > > c 1 a N = k i = 1 ( c iokck>>c1

N=i=1k(cii).

Questo numero ha una semplice interpretazione. Se ordiniamo queste sequenze lessicograficamente, allora conta il numero di sequenze più piccole.N

Per decodificare, basta assegnare a il valore più grande tale che ( c kcke decodificaN- ( ck(ckk)N come conseguenza(k-1).N(ckk)(k1)


4

Il numero totale di coppie di numeri non ordinate in un set di è N ( N + 1 ) / 2 . Il numero totale di coppie non ordinate di numeri distinti è N ( N - 1 ) / 2 . Richiede 2 log 2 ( N ) = log 2NN(N+1)/2N(N1)/2 bit per rappresentare una coppia ordinata di numeri, e se si ha uno meno bit, si può rappresentare elementi di uno spazio di fino a N 2 / 22log2(N)=log2(N2)N2/2. Il numero di coppie non ordinate non necessariamente distinte è leggermente più della metà del numero di coppie ordinate, quindi non è possibile salvare un po 'nella rappresentazione; il numero di coppie distinte non ordinate è leggermente inferiore alla metà, quindi puoi risparmiare un po '.

Per uno schema pratico che è facile da calcolare, con è una potenza di 2, puoi lavorare sulla rappresentazione bit a bit. Prendi a = x y dove è l'operatore XOR (bit a bit esclusivo o). La coppia { x , y } può essere recuperata da ( a , x ) o ( a , y ) . Ora cercheremo un trucco per risparmiare un po 'nella seconda parte, e dare un ruolo simmetrica per x e yNa=xy{x,y}(a,x)(a,y)xyin modo che l'ordine non possa essere recuperato. Dato il calcolo della cardinalità sopra, sappiamo che questo schema non funzionerà nel caso in cui .x=y

Se allora c'è qualche posizione in cui differiscono. Scriverò x i per l' i esimo bit di x (cioè x = i x i 2 i ), e allo stesso modo per y . Lasciare k prendere la posizione più piccolo pezzo in cui x ed y differiscono: k è il più piccolo i tale che x iy i . k è il più piccolo i tale che un i =xyxiixx=ixi2iykxykixiyiki : possiamo recuperare k da a . Let bai=1kab o o y con il k bit bit cancellato (ovvero b = i < k x i 2 i + i > k x i 2 i - 1 oppure b = i < k y i 2 i + i > k y i 2 i -xykb=i<kxi2i+i>kxi2i1 ) - per rendere simmetrica la costruzione, selezionarexse x k =0e y k =1, quindi selezionareyse x k =1e y k =0. Utilizzare(a,b)come rappresentazione compatta della coppia. La coppia originale può essere recuperata calcolando il bit di ordine più basso impostato ina, inserendo uno 0 bit in questa posizione inb(ottenendo uno dixoy) e prendendo il xor di quel numero conb=i<kyi2i+i>kyi2i1xxk=0yk=1yxk=1yk=0(a,b)abxya

ab

In pseudocodice, con ^, &, |, <<, >>, ~essendo C-like operatori bit (XOR, e, o, sinistra-shift, shift destro, complemento):

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

Una prova non costruttiva: ci sono (232×232232)/2=231(2321)<263 unordered pairs of different 32-bit integers.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.