Bit-Umkehr einer ganzen Zahl zu ignorieren integer Größe und endianness
Gegeben eine Ganzzahl typedef:
typedef unsigned int TYPE;
oder
typedef unsigned long TYPE;
Ich habe den folgenden code zum umkehren der bits eines integer:
TYPE max_bit= (TYPE)-1;
void reverse_int_setup()
{
TYPE bits= (TYPE)max_bit;
while (bits <<= 1)
max_bit= bits;
}
TYPE reverse_int(TYPE arg)
{
TYPE bit_setter= 1, bit_tester= max_bit, result= 0;
for (result= 0; bit_tester; bit_tester>>= 1, bit_setter<<= 1)
if (arg & bit_tester)
result|= bit_setter;
return result;
}
Muss man nur noch zuerst ausführen reverse_int_setup () - speichert eine ganze Zahl mit dem höchsten bit eingeschaltet, dann wird jeder Aufruf zum reverse_int(arg) gibt arg mit seine bits invertiert (werden als Schlüssel verwendet, um einen binären Baum, ergriffen von einer zunehmenden Zähler, aber das ist mehr oder weniger irrelevant).
Gibt es eine Plattform-unabhängige Art und Weise zu haben, in compile-time den richtigen Wert für max_int nach dem Aufruf reverse_int_setup(); Ansonsten gibt es einen Algorithmus, den Sie betrachten besser/schlanker als die, die ich habe für reverse_int()?
Dank.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dieser Zeit habe ich die "Anzahl der bits, die' Idee von der TK, sondern machte es ein wenig mehr tragbar, indem Sie nicht davon ausgehen, dass ein byte enthält 8 bits und stattdessen über das macro CHAR_BIT. Der code effizienter ist nun (mit der inneren for-Schleife entfernt). Ich hoffe, der code ist auch etwas weniger kryptisch aus dieser Zeit. 🙂
Die Notwendigkeit für die Verwendung von count ist, dass die Anzahl der Positionen, die wir haben, um shift ein bit ändert sich bei jeder iteration - wir verschieben das bit ganz rechts um 31 Positionen (davon 32 bit-Zahl), die zweite am weitesten rechts liegenden bit um 29 Positionen und so weiter. Daher zählen müssen, verringern sich mit jeder iteration, wie ich erhöht.
Hoffe, dass bisschen info beweist hilfreich, den code zu verstehen...
Folgende Programm dient zu zeigen, ein schlanker Algorithmus die Umkehrung der bits, die kann leicht erweitert werden, um zu behandeln 64bit zahlen.
Dieser code sollte keine Fehler enthalten, und wurde getestet mit 0x12345678 zu produzieren 0x1e6a2c48 welche Antwort richtig ist.
Dies funktioniert gut in gcc unter Windows, aber ich bin mir nicht sicher, ob es völlig Plattform-unabhängig. Ein paar Orte von Interesse sind:
die Bedingung in der for-Schleife - es wird davon ausgegangen, dass wenn Sie mit der linken shift 1 über das bit ganz Links, bekommen Sie entweder eine 0 mit der 1 'Herausfallen' (was ich erwarten würde, und was die guten alten Turbo-C gibt iirc), oder die 1. Kreise um und erhalten Sie eine 1 (was zu sein scheint der gcc-Verhalten).
die Bedingung in der inneren while-Schleife: siehe oben. Aber es ist schon eine seltsame Sache passiert hier: in diesem Fall gcc scheint lassen Sie die 1 fallen und nicht Kreis rund!
Den code könnte sich als kryptisch: wenn Sie interessiert sind und benötigen eine Erklärung, bitte zögern Sie nicht zu Fragen - ich werde es bis irgendwo.
@ΤΖΩΤΖΙΟΥ
In der Antwort zu ΤΖΩΤΖΙΟΥ 's Kommentare, ich präsentiere modifizierte version von oben, das hängt davon ab, eine Obere Grenze für die bit-Breite.
Hinweise:
Entschuldige ich mich im Voraus für die Codierung Verbrechen ich begangen oben Gnade guter Herr!
Gibt es eine schöne Sammlung von "Bit Twiddling Hacks", einschließlich einer Vielzahl von einfachen und nicht so einfachen bit-Umkehr-algorithmen codiert C an http://graphics.stanford.edu/~seander/bithacks.html.
Mir persönlich gefällt das "Offensichtliche" algorigthm ( http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious ), weil, gut, das ist klar. Einige andere mögen, erfordern Sie weniger Anweisungen ausführen. Wenn ich wirklich brauchen, um zu optimieren, das heck aus, was ich wählen kann, die nicht so offensichtlich, aber schnellere Versionen. Ansonsten, für die Lesbarkeit, Wartbarkeit und Portabilität, die ich wählen würde, die Offensichtlich einen.
Hier ist eine allgemein nützliche Variante. Sein Vorteil ist seine Fähigkeit, in Situationen zu arbeiten, wo die bit-Länge des Wertes rückgängig gemacht werden -- das Codewort -- ist unbekannt, aber garantiert nicht mehr als einen Wert nennen wir maxLength. Ein gutes Beispiel für diesen Fall ist der Huffman-code kennen.
Den code unten funktioniert auf Codewörter von 1 bis 24 bit Länge. Es wurde optimiert für die schnelle Ausführung auf einem Pentium D. Hinweis, dass der Zugriff auf die lookup-Tabelle so viele wie 3 mal pro verwenden. Ich experimentierte mit viele Variationen, reduziert sich diese Zahl auf 2, auf Kosten einer größeren Tabelle (4096 und 65.536 Einträge). Diese version mit der 256-byte-Tabelle, war der klare Sieger, teilweise, weil es so vorteilhaft für die Tabelle Daten in die caches, und vielleicht auch, weil der Prozessor verfügt über einen 8-bit-lookup-Tabelle/übersetzung-Anweisung.
Wie etwa:
(Ich gehe davon aus, dass Sie wissen, wie viele bits mit dem Wert hält und es ist gespeichert in number_of_bits)
Offensichtlich temp benötigt, um die längste vorstellbare Daten-Typ und beim kopieren von temp wieder in Wert, alle die überflüssigen bits, die in temp sollte auf Magische Weise verschwinden (denke ich!).
Oder, das 'c' Weg wäre, zu sagen :
Ihrer Wahl
Können wir speichern Sie die Ergebnisse auf die Umkehrung aller möglichen 1-byte-Sequenzen in einem array (256 verschiedene Einträge), dann verwenden Sie eine Kombination von lookups in dieser Tabelle und einige oring-Logik zu erhalten, das Gegenteil von integer ist.
Hier ist eine variation und Korrektur der TK-Lösung, die könnte klarer sein als die Lösungen von sundar. Es braucht einzelne bits von t und schiebt Sie in return_val:
Den generischen Ansatz hat, würde die Arbeit für die Objekte von jedem Typ in jeder Größe wäre eine Umkehrung der bytes des Objekts, und die umgekehrte Reihenfolge der bits in jedem byte. In diesem Fall wird die bit-Ebene-Algorithmus ist an eine konkrete Anzahl von bits (ein byte), während die "variable" - Logik (hinsichtlich der Größe) angehoben wird, auf der Ebene von ganzen bytes.
Hier ist meine Verallgemeinerung von freespace Lösung (im Falle, dass wir eines Tages 128-bit-Maschinen). Es ergibt sich im Sprung-gratis-code bei der Kompilierung mit gcc -O3, und ist offensichtlich unempfindlich für die definition von foo_t auf vernünftige Maschinen. Leider es hängt nicht von shift wird eine Kraft von 2!
Bei bit-Umkehr ist mal kritisch, und vor allem in Verbindung mit FFT, ist der beste store das ganze etwas Umgekehrt array. In jedem Fall, dieses array wird in der Größe kleiner als die Wurzeln der Einheit, die vorausberechnete in FFT, Cooley-Tukey-Algorithmus. Eine einfache Möglichkeit zur Berechnung des array ist:
[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]
.