Całkowita liczba nieuporządkowanych par liczb w zbiorze wynosi . Całkowita liczba nieuporządkowanych par odrębnych liczb wynosi . Potrzeba bitów do przedstawienia uporządkowanej pary liczb, a jeśli masz jeden bit mniej, możesz reprezentować elementy przestrzeni do . Liczba nieuporządkowanych niekoniecznie odrębnych par jest nieco większa niż połowa liczby uporządkowanych par, więc nie możesz zapisać trochę w reprezentacji; liczba nieuporządkowanych odrębnych par jest nieco mniejsza niż połowa, więc możesz trochę zaoszczędzić.NN(N+1)/2N(N−1)/22log2(N)=log2(N2)N2/2
Aby uzyskać praktyczny schemat, który jest łatwy do obliczenia, przy czym jest potęgą 2, możesz pracować z reprezentacją bitową. Weźmy gdzie jest operatorem XOR (bitowe wykluczenie lub). Pary można odzyskać z lub . Teraz szukamy sposobu na zaoszczędzenie jednego bitu w drugiej części i nadanie i symetrycznej roli, aby nie można było odzyskać kolejności. Biorąc pod uwagę powyższe obliczenia liczności, wiemy, że ten schemat nie zadziała w przypadku, gdy .Na=x⊕y⊕{x,y}(a,x)(a,y)xyx=y
Jeśli to jest trochę pozycji, w której się różnią. Napiszę dla tego bitu (tj. ), i podobnie dla . Niech przyjmie najmniejszą pozycję bitu, w której i różnią się: jest najmniejszą taką, że . jest najmniejszym takim, że : możemy odzyskać z . Niech będzie albo albox≠yxiixx=∑ixi2iykxykixi≠yikiai=1kabxyz tym bitem skasowanym (tj. lub ) - aby konstrukcja była symetryczna, wybierz jeśli i , i wybierz jeśli i . Użyj jako zwartej reprezentacji pary. Pierwotną parę można odzyskać, obliczając bit najniższego rzędu ustawiony w , wstawiając bit 0 w tej pozycji (uzyskując jeden z lub ) i biorąc xor tej liczby za pomocąkb=∑i<kxi2i+∑i>kxi2i−1b=∑i<kyi2i+∑i>kyi2i−1xxk=0yk=1yxk=1yk=0(a,b)abxya (uzyskując drugi element pary).
W tej reprezentacji może być dowolną liczbą niezerową, a może być dowolną liczbą o połowie zakresu. Jest to kontrola rozsądku: otrzymujemy dokładnie oczekiwaną liczbę reprezentacji nieuporządkowanych par.ab
W Pseudokod, z ^
, &
, |
, <<
, >>
, ~
to C-like operatorów bitowe (XOR, AND, OR, lewy shift prawym zmianowych, dopełniacza):
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)