Python kehrt ein binäres Muster innerhalb einer Ganzzahl um
Gibt es eine schnelle Möglichkeit, eine Binärzahl in Python umzukehren?
Beispiel: Ich habe die Nummer 11 in binär 0000000000001011 mit 16 Bits. Jetzt suche ich nach einer schnellen Funktion f, die 1101000000000000 (dezimal 53248) zurückgibt. Nachschlagetabellen sind keine Lösungen, da ich möchte, dass sie auf 32-Bit-Zahlen skaliert werden. Vielen Dank für Ihre Mühen.
Bearbeiten:
Aufführungen . Ich habe den Code für alle 2 ^ 16 Muster mehrmals getestet.
Gewinner sind die teilweise nachgeschlagenen Tabellen: 30ms
2.
int(format(num, '016b')[::-1], 2)aus den Kommentaren: 56ms3.
x = ((x & 0x00FF) << 8) | (x >> 8)65 msIch hatte nicht erwartet, dass mein Ansatz so schrecklich langsam sein würde, aber es ist so. ca. 320ms. Kleine Verbesserung durch Verwendung von + anstelle von | 300ms
bytes(str(num).encode('utf-8'))kämpfte um den 2. Platz, aber irgendwie lieferte der Code keine gültigen Antworten. Höchstwahrscheinlich, weil ich einen Fehler gemacht habe, indem ich sie wieder in eine ganze Zahl umgewandelt habe.
Vielen Dank für Ihre Eingabe. Ich war ziemlich überrascht.
Antworten
Dies kann mit einer kleinen 8-Bit-Nachschlagetabelle schneller gehen:
num = 11
# One time creation of 8bit lookup
rev = [int(format(b, '08b')[::-1], base=2) for b in range(256)]
# Run for each number to be flipped.
lower_rev = rev[num & 0xFF] << 8
upper_rev = rev[(num & 0xFF00) >> 8]
flipped = lower_rev + upper_rev
Ich denke, Sie können einfach das Schneiden verwenden, um das zu bekommen, wonach Sie suchen:
b=bytes('0000000000001011'.encode('utf-8'))
>>> b
b'0000000000001011'
>>> b[::-1]
b'1101000000000000'
Es gibt dies, aber in Python scheint es langsamer zu sein als die von Matthias vorgeschlagene int-> str-> intLösung.
x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1)
x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2)
x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4)
x = ((x & 0x00FF) << 8) | (x >> 8)
Mein aktueller Ansatz besteht darin, über Bitverschiebung und Maske auf die Bits zuzugreifen und sie in der Spiegelnummer zu verschieben, bis sie ihr Ziel erreichen. Trotzdem habe ich das Gefühl, dass es Raum für Verbesserungen gibt.
num = 11
print(format(num, '016b'))
right = num
left = 0
for i in range(16):
tmp = right & 1
left = (left << 1 ) | tmp
right = right >> 1
print(format(left, '016b'))