Die Funktion struct.pack() ermöglicht das Konvertieren von Ganzzahlen mit bis zu 64 Bit in Byte-Strings. Was ist der effizienteste Weg, um eine noch größere Ganzzahl zu packen? Ich würde lieber keine Abhängigkeit von Nicht-Standard-Modulen wie PyCrypto (die num_to_bytes() bereitstellt) hinzufügen.Effizientes beliebiges Integer-Packen in voller Größe in Python
Antwort
Wie von S.Lott in einem Kommentar vorgeschlagen, nur die Zahl in eine Zeichenfolge konvertieren und diese Zeichenfolge packen. Zum Beispiel
x = 2 ** 12345
struct.pack("40s", str(x))
Das ist noch weniger effizient als nur die Zeichenfolgendarstellung der Ganzzahl zu speichern, da das int mit Nullbytes aufgefüllt wird. –
Die Frage ist unklar, welche Art von Effizienz erforderlich ist? Suchen wir nach der effizientesten Raumnutzung? Oder vielleicht die geringste Verarbeitungszeit, um die Struktur zu packen? Ist Effizienz sogar eine große Sache? Die Frage wurde nach der effizientesten Antwort gestellt, aber die Leute optimieren oft vorzeitig. –
das Plakat Unter der Annahme, will eine große Ganzzahl als eine binäre Zeichenfolge packen, das heißt nicht ein Byte Speicher pro Ziffer der Nummer verwenden. Eine Möglichkeit, dies zu tun, scheint zu sein:
import marshal
a = 47L
print marshal.dumps(a)
Diese Drucke:
'l\x01\x00\x00\x00/\x00'
Ich kann nicht sagen, dass ich verstehe, wie diese Bits zu interpretieren, jetzt ...
Das geht in die richtige Richtung, aber es hat immer noch zwei redundante Bytes an der Front. –
@Mike: Eigentlich mehr als das - ich denke, die "l" und ersten 4 Ziffern sind nur eine Zählung des Inhalts, gefolgt von einem einzelnen Byte ("/" == chr (47)) und eine Null am Ende. Es sieht auch so aus, als würde Marshal ein komplexeres Codierungsschema machen, das nur die rohen Bytes enthält (schauen Sie sich zum Beispiel Dumps (2 ** 64-1) an und nicht die 0x7f Bytes in der Mitte. – Brian
I nehmen Sie es, Sie meinen, Sie wollen nur so viele Bytes verwenden, wie Sie die Zahl darstellen müssen? z.B. wenn die Zahl:
- 255 oder weniger würden Sie nur 1 Byte
- 65535 oder weniger 2 Byte
- 16777215 oder weniger 3 Bytes
- etc etc
über die Verwendung Psion PDA haben sie normalerweise ein Packschema, in dem Sie das erste Byte lesen, erkennen, ob es das höchste Bit gesetzt hat und dann ein anderes Byte lesen, wenn es das hat. Auf diese Weise würden Sie einfach weiter Bytes lesen, bis Sie die "volle" Nummer lesen. Dieses System funktioniert ziemlich gut, wenn die meisten Zahlen, mit denen Sie es zu tun haben, ziemlich klein sind, da Sie normalerweise nur ein oder zwei Bytes pro Nummer verwenden.
Die Alternative besteht darin, ein (oder mehrere) Bytes zu haben, die die Anzahl der insgesamt verwendeten Bytes darstellen, aber zu diesem Zeitpunkt ist es in Python sowieso eine Zeichenfolge. d.h. es ist eine Folge von 256 Basisziffern.
Haben Sie etwas wie dies bedeuten:
def num_to_bytes(num):
bytes = []
num = abs(num) # Because I am unsure about negatives...
while num > 0:
bytes.append(chr(num % 256))
num >>= 8
return ''.join(reversed(bytes))
def bytes_to_num(bytes):
num = 0
for byte in bytes:
num <<= 8
num += ord(byte)
return num
for n in (1, 16, 256, 257, 1234567890987654321):
print n,
print num_to_bytes(n).encode('hex'),
print bytes_to_num(num_to_bytes(n))
Welche zurück:
1 01 1
16 10 16
256 0100 256
257 0101 257
1234567890987654321 112210f4b16c1cb1 1234567890987654321
Ich bin nur nicht sicher, was Negative zu tun ... Ich bin nicht so vertraut mit etwas Twittern.
EDIT: Eine andere Lösung (die durch meine Tests etwa 30% schneller läuft):
def num_to_bytes(num):
num = hex(num)[2:].rstrip('L')
if len(num) % 2:
return ('0%s' % num).decode('hex')
return num.decode('hex')
def bytes_to_num(bytes):
return int(bytes.encode('hex'), 16)
Ja, das ist was ich meine, und Ich habe vor einiger Zeit eine solche Funktion geschrieben, aber ich wollte etwas, das einfacher zu portieren ist, wie einen Listenverständnistrick oder (besser) eine Bibliotheksfunktion, von der ich nichts wusste. – noamtm
Ich habe gerade einen neuen Artikel mit eingebaut int/hex transcoding und hex/str transcondition ... Es geht auch ein bisschen schneller! –
@noamtm: Bitte aktualisieren Sie die Frage mit zusätzlichen Fakten.Verbergen Sie nicht nur Informationen in Kommentaren. –
Das ist ein bisschen hacky, aber man konnte über die Hex-String-Darstellung gehen und dort mit Binär der hex-Codec:
>>> a = 2**60
>>> a
1152921504606846976L
>>> hex(a)
'0x1000000000000000L'
>>> hex(a).rstrip("L")[2:].decode('hex')
'\x10\x00\x00\x00\x00\x00\x00\x00' # 8bytes, as expected.
>>> int(_.encode('hex'), 16)
1152921504606846976L
Es bricht ein wenig, weil der hex-Codec eine gerade Anzahl von Ziffern erfordert, so dass Sie für das zu Pad benötigen, und Sie werden eine Flagge zu handhaben negative Zahlen festlegen müssen.Hier ist eine generische Packung/auspacken:
def pack(num):
if num <0:
num = (abs(num) << 1) | 1 # Hack - encode sign as lowest bit.
else:
num = num << 1
hexval = hex(num).rstrip("L")[2:]
if len(hexval)%2 ==1: hexval = '0' + hexval
return hexval.decode('hex')
def unpack(s):
val = int(s.encode('hex'), 16)
sign = -1 if (val & 1) else 1
return sign * (val>>1)
for i in [10,4534,23467, 93485093485, 2**50, 2**60-1, -1, -20, -2**60]:
assert unpack(pack(i)) == i
Mit all das zum Auffüllen etc Hantieren erforderlich, ich bin nicht sicher, es ist viel besser als eine handgerollte Lösung though.
- 1. WordPress - Bild in voller Größe Option deaktivieren
- 2. WordPress: Bild in voller Größe in Miniaturansicht laden
- 3. UIImagePickerController Kräfte Bilder in anderen Ansichten in voller Größe
- 4. Fügen Sie eine Schaltfläche zu voller Größe in fancybox v2
- 5. Wie kann ich eine A4-Seite in voller Größe drucken?
- 6. Erstellen Sie ein benutzerdefiniertes Kalendersteuerelement in voller Größe
- 7. Anklickbare Panels in voller Größe auf Angular UI Accordion (?)
- 8. Erhalten Sie in voller Größe Bild von Facebook Grafik API
- 9. In voller Länge Navbar
- 10. in voller Höhe Bild
- 11. Effizientes Multiprocessing der massiven, brachialen Kraftmaximierung in Python 3
- 12. Effizientes Zeichnen von Linien mit Python
- 13. Wie effizientes Paging in Mongodb
- 14. Effizientes veränderbares Byte-Array in nativem Lua
- 15. Effizientes Berechnen der Worthäufigkeit in einer Zeichenfolge
- 16. Erfassen Sie ein Foto und zeigen Sie es in voller Größe in ImageView in Android
- 17. Ein beliebiges Zeichen (einschließlich Zeilenumbrüche) in sed
- 18. Effizientes Importieren von Modulen in Django-Ansichten
- 19. HighCharts in voller Breite Ausgabe
- 20. CSS-Layout mit voller Größe linker Navigationsleiste und Header
- 21. Effizientes Laden einer großen Mat in den Speicher in OpenCV
- 22. Wie füge ich zwei Seiten in voller Größe in Scrollview (vertikal) auf Xamarin.forms hinzu?
- 23. Jcrop-Kreisauswahl auf reduzierten großen Bildern zeigt das Bild in voller Größe in der Vorschau-Auswahlzone
- 24. Schieberegler in voller Breite in jquery mobile?
- 25. Voller Text in Pin-Label in Xamarin
- 26. Effizientes Mapping von Spieleinheiten in Java
- 27. Effizientes Zählen gruppierter Elemente in Pandas
- 28. Effizientes Speichern der Daten in Hive
- 29. Effizientes Abbrechen der Keyframe-Animation in Swift
- 30. Berechnung Effizientes einzigartige Permutationen in einem Satz
Nicht sicher, wovon Sie sprechen. Möchten Sie die String-Version eines Python long in eine Struktur einfügen? Die String-Version von long ist eine Zeichenfolge. Sie packen es wie jede andere Saite. Was ist deine wahre Frage? –
Das OP möchte so effizient wie möglich eine beliebig große Ganzzahl in eine sinnvolle Byte-String-Darstellung packen. –