Bei dieser Frage geht es darum, wie viele Bits zum Speichern eines Bereichs erforderlich sind. Oder anders ausgedrückt: Wie kann der maximale Bereich für eine bestimmte Anzahl von Bits gespeichert werden?
Stellen Sie sich vor, wir möchten einen Unterbereich zwischen 0 und 255 speichern.
Also zum Beispiel 45-74.
Wir können das obige Beispiel als zwei vorzeichenlose Bytes speichern, aber es fällt mir auf, dass es dort eine gewisse Redundanz der Informationen geben muss. Wir wissen, dass der zweite Wert größer als der erste ist. In dem Fall, dass der erste Wert groß ist, sind weniger Bits für den zweiten Wert erforderlich, und in dem Fall, dass der zweite Wert groß ist, sind weniger Bits für den ersten Wert erforderlich .
Ich vermute, dass jede Komprimierungstechnik zu einem geringfügigen Ergebnis führen würde. Daher ist es möglicherweise eine bessere Frage, sich die Frage zu stellen, wie hoch der maximale Bereich ist, der in einem Byte gespeichert werden kann. Dies sollte größer sein als das, was durch die getrennte Speicherung der beiden Zahlen erreicht werden kann.
Gibt es dafür Standardalgorithmen?
quelle
Antworten:
Zählen Sie einfach die Anzahl der möglichen Bereiche. Es gibt 256 Bereiche mit Untergrenze 0 (0-0, 0-1, ... 0-254, 0-255), 255 Bereiche mit Untergrenze 1, ... und schließlich 1 Bereich mit Untergrenze 255 (255- 255). Die Gesamtzahl ist also (256 + 255 + ... + 1) = 257 * 128 = 32.896. Da dies etwas höher als 2 15 = 32.768 ist, benötigen Sie immer noch mindestens 16 Bits (2 Bytes), um diese Informationen zu speichern.
Im Allgemeinen beträgt die Anzahl der möglichen Bereiche für Zahlen von 0 bis n-1 n * (n + 1) / 2. Dies ist weniger als 256, wenn n 22 oder weniger ist: n = 22 ergibt 22 * 23/2 = 253 Möglichkeiten. So ein Byte reicht für Teilbereiche von 0-21 .
Ein anderer Weg, um das Problem zu betrachten, ist der folgende: Das Speichern eines Paars von ganzen Zahlen im Bereich von 0 bis n-1 entspricht fast dem Speichern eines Unterbereichs von 0- (n-1) plus einem einzelnen Bit, das bestimmt, ob die erste Zahl vorliegt ist niedriger oder höher als die zweite. (Der Unterschied ergibt sich aus dem Fall, in dem beide Ganzzahlen gleich sind, diese Chance jedoch mit zunehmendem Wert von n immer kleiner wird.) Aus diesem Grund können Sie mit dieser Technik nur ein einziges Bit speichern, und dies ist wahrscheinlich der Hauptgrund, warum sie selten verwendet wird.
quelle
n * (n + 1) / 2 + 1
! Eine winzige Veränderung.Für solch eine kleine Anzahl von Bits ist es unmöglich, viele Bits zu speichern, wie Glorfindel herausgestellt hat . Wenn die von Ihnen verwendete Domain jedoch einige Bits mehr enthält, können Sie im Durchschnitt erhebliche Einsparungen erzielen, indem Sie Bereiche mit dem Startwert und einem Delta codieren.
Nehmen wir an, die Domain sind die ganzen Zahlen, also 32 Bit. Bei der naiven Methode benötigen Sie 64 Bit (Anfang, Ende), um einen Bereich zu speichern.
Wenn wir zu einer Kodierung von (Start, Delta) wechseln, können wir daraus das Ende des Bereichs konstruieren. Wir wissen, dass im schlimmsten Fall der Start 0 ist und das Delta 32 Bits hat.
2 ^ 5 ist 32, also codieren wir die Länge des Deltas in fünf Bits (keine Nulllänge, addieren immer 1) und die Codierung wird (Start, Länge, Delta). Im schlimmsten Fall kostet dies 32 * 2 + 5 Bit, also 69 Bit. Im schlimmsten Fall, wenn alle Bereiche lang sind, ist dies schlechter als die naive Codierung.
Im besten Fall kostet es 32 + 5 + 1 = 38 Bit.
Wenn Sie also viele Bereiche codieren müssen und diese Bereiche jeweils nur einen kleinen Teil Ihrer Domain abdecken, belegen Sie mit dieser Codierung im Durchschnitt weniger Speicherplatz . Es spielt keine Rolle, wie die Starts verteilt sind, da der Start immer 32 Bit dauert, aber es spielt keine Rolle, wie die Längen der Bereiche verteilt sind. Je kleiner die Länge ist, desto besser ist die Komprimierung. Je mehr Bereiche über die gesamte Länge der Domäne verfügbar sind, desto schlechter wird die Codierung.
Wenn Sie jedoch viele Bereiche um ähnliche Startpunkte gruppieren (z. B. weil Sie Werte von einem Sensor erhalten), können Sie noch größere Einsparungen erzielen. Sie können dieselbe Technik auf den Startwert anwenden und eine Abweichung verwenden, um den Startwert zu versetzen.
Nehmen wir an, Sie haben 10000 Bereiche. Die Bereiche sind um einen bestimmten Wert gruppiert. Sie codieren die Vorspannung mit 32 Bits.
Bei Verwendung des naiven Ansatzes würden Sie 32 * 2 * 10 000 = 640 000 Bits benötigen, um alle diese Bereiche zu speichern.
Das Codieren der Vorspannung dauert 32 Bits, und das Codieren jedes Bereichs dauert im besten Fall dann 5 + 1 + 5 + 1 = 12 Bits, was insgesamt 120 000 + 32 = 120 032 Bits ergibt. Im schlimmsten Fall benötigen Sie 5 + 32 + 5 + 32 Bit, also 74 Bit, für insgesamt 740 032 Bit.
Dies bedeutet, dass wir für 10 000 Werte in einer Domäne, für deren Codierung 32 Bit erforderlich sind, Folgendes erhalten
Wenn Sie die naive Codierung als Basis nehmen, bedeutet dies entweder Einsparungen von bis zu 81,25% oder bis zu 15,625% mehr Kosten.
Je nachdem, wie Ihre Werte verteilt sind, sind diese Einsparungen erheblich. Kennen Sie Ihre Geschäftsdomäne! Wissen Sie, was Sie codieren möchten.
Als Erweiterung können Sie auch die Vorspannung ändern. Wenn Sie die Daten analysieren und Wertegruppen identifizieren, können Sie die Daten in Gruppen sortieren und jede dieser Gruppen separat mit einer eigenen Verzerrung codieren. Dies bedeutet, dass Sie diese Technik nicht nur auf Bereiche anwenden können, die um einen einzelnen Startwert gruppiert sind, sondern auch auf Bereiche, die um mehrere Werte gruppiert sind.
Wenn Ihre Startpunkte gleichmäßig verteilt sind, funktioniert diese Codierung nicht wirklich gut.
Diese Kodierung ist offensichtlich extrem schlecht zu indizieren. Sie können den x-ten Wert nicht einfach ablesen. Es kann so ziemlich nur sequentiell gelesen werden. Was in manchen Situationen angebracht ist, z. B. Streaming über das Netzwerk oder Massenspeicher (z. B. auf Band oder Festplatte).
Das Auswerten der Daten, das Gruppieren und das Auswählen der richtigen Verzerrung kann ein erheblicher Aufwand sein und erfordert möglicherweise eine Feinabstimmung, um optimale Ergebnisse zu erzielen.
quelle
Diese Art von Problem ist Gegenstand von Claude Shannons wegweisendem Aufsatz " Eine mathematische Theorie der Kommunikation" , in dem das Wort "Bit" und mehr oder weniger erfundene Datenkomprimierung eingeführt wurden.
Die allgemeine Idee ist, dass die Anzahl der zum Codieren eines Bereichs verwendeten Bits umgekehrt proportional zur Wahrscheinlichkeit des Auftretens dieses Bereichs ist. Angenommen, der Bereich 45-74 erscheint ungefähr 1/4 der Zeit. Sie können sagen, dass die Sequenz 00 45-74 entspricht. Um den Bereich 45-74 zu codieren, geben Sie "00" aus und halten dort an.
Nehmen wir auch an, dass die Bereiche 99-100 und 140-155 jeweils etwa 1/8 der Zeit erscheinen. Sie können sie jeweils mit einer 3-Bit-Sequenz codieren. Alle 3 Bits reichen aus, solange sie nicht mit „00“ beginnen, das bereits für den Bereich 45-74 reserviert ist.
Sie können auf diese Weise fortfahren, bis jeder mögliche Bereich eine Codierung aufweist. Der am wenigsten wahrscheinliche Bereich benötigt möglicherweise mehr als 100 Bit. Aber das ist okay, weil es selten erscheint.
Es gibt Algorithmen, um die optimale Kodierung zu finden. Ich werde nicht versuchen, sie hier zu erklären, aber Sie können mehr finden, indem Sie den obigen Link besuchen oder nach "Informationstheorie", "Shannon-Fanocodierung" oder "Huffman-Codierung" suchen.
Wie bereits erwähnt, ist es wahrscheinlich besser, die Startnummer und die Differenz zwischen Start- und Endnummer zu speichern. Sie sollten eine Codierung für den Start und eine andere für den Unterschied verwenden, da sie unterschiedliche Wahrscheinlichkeitsverteilungen haben (und ich vermute, dass letztere redundanter ist). Wie von Polygnomen vorgeschlagen, hängt der beste Algorithmus von Ihrer Domain ab.
quelle
So erweitern Sie die Antwort von @Glorfindel:
Wie n → ∞, (n - 1) → n. Also Ω (Bereiche) → n² / 2 und log (Ω (Bereiche)) → (2n - 1). Da die naive Codierung 2n Bit benötigt, spart die asymptotische maximale Komprimierung nur 1 Bit.
quelle
Es gibt eine ähnliche Antwort, aber um eine optimale Komprimierung zu erzielen, benötigen Sie:
Wichtig ist, dass Nummer 2 bedeutet, dass Sie die Dinge so codieren möchten, dass die informativsten Werte (pro codiertem Bit) an erster Stelle stehen. Während ich beispielsweise vorschlug, eine sortierte Liste "wie sie ist" zu codieren, wäre es normalerweise klüger, sie als "binären Baum" zu
len
codierenlen/2
. Angenommen, es hatte die Breite w. Jetzt kennen Sie alle Elemente, bevor sie irgendwo in [0, w] eine Breite haben, und alle Elemente, nachdem sie irgendwo in [w, max val you accept] eine Breite haben. Wiederholen Sie diesen Vorgang rekursiv (Unterteilen Sie jede halbe Liste erneut in zwei Hälften usw.), bis Sie dielen
Elemente abgedeckt haben (sofern nichts anderes festgelegt ist, möchten Sie sie codierenlen
zuerst, damit Sie sich nicht mit dem Beenden von Tokens herumschlagen müssen). Wenn "max val you accept" wirklich offen ist, kann es sinnvoll sein, zuerst den höchsten Wert zu codieren, der tatsächlich in Ihren Daten erscheint, dh das letzte Element, und dann die binäre Partitionierung durchzuführen. Wiederum ist das, was am informativsten ist, pro Bit zuerst.Wenn Sie zuerst die Breite des Intervalls codieren und den maximal möglichen Wert kennen, mit dem Sie es zu tun haben, können Sie natürlich alle Startwerte ausschließen, die zu einem Überlauf führen würden ... Sie haben die Idee. Transformieren und ordnen Sie Ihre Daten so, dass Sie so viel wie möglich auf den Rest der Daten schließen können, während Sie sie dekodieren. Ein optimaler Entropie-Kodierungsalgorithmus stellt sicher, dass Sie keine Bits für Kodierungsinformationen verschwenden, die Sie "bereits kennen". .
quelle