Python kehrt ein binäres Muster innerhalb einer Ganzzahl um

Sep 02 2020

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: 56ms

  • 3. x = ((x & 0x00FF) << 8) | (x >> 8)65 ms

  • Ich 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

3 HL Sep 02 2020 at 04:36

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
1 Ethan Sep 02 2020 at 03:55

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'
1 superbrain Sep 02 2020 at 04:27

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)
1 DuDa Sep 02 2020 at 03:48

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'))