8
votes

Comment puis-je écrire un grand entier comme binaire en python?

en Python, de longs entiers ont une précision illimitée. Je voudrais écrire un entier de 16 octets (128 bits) à un fichier. struct de la bibliothèque standard ne prend en charge que 8 entiers d'octets. Array a la même limitation. Y a-t-il un moyen de le faire sans masquer et déplacer chaque entier?

Quelques éclaircissements ici: J'écris à un dossier qui va être lu dans des programmes non python, alors le cornichon est sorti. Les 128 bits sont utilisés.


3 commentaires

On dirait qu'il l'a déjà fait - STRIT de la bibliothèque standard ne supporte que 8 entiers d'octets.


Avez-vous besoin de l'ensemble de la plage de 128 bits ou des 64 bits inférieurs, avez-vous besoin d'entiers signés?


duplicaté possible de Y a-t-il un moyen plus rapide de convertir un grand entier arbitraire à une grande séquence d'Endian d'octets?


9 Réponses :


0
votes

Vous pouvez coraller l'objet à binaire, utilisez des tampons de protocole (je ne sais pas s'ils vous permettent de sérialiser des entiers de précision illimités cependant) ou de BSON si vous ne souhaitez pas écrire de code.

Mais écrire une fonction qui décharge 16 entiers d'octets en déplaçant qu'il ne faut pas être si difficile à faire si ce n'est pas le temps critique.


0 commentaires

5
votes

Deux solutions possibles:

  1. Just Pickle Votre long entiers. Cela écrira l'entier dans un format spécial qui lui permet d'être lu à nouveau, si c'est tout ce que vous voulez.

  2. Utilisez le deuxième extrait de code dans Cette réponse Pour convertir le long Int à une grosse chaîne Endian (qui peut être facilement changé en peu d'Endian si vous préférez) et écrivez cette chaîne à votre dossier.

    Le problème est que la représentation interne des BIGINTS n'inclut pas directement les données binaires que vous demandez.


0 commentaires

1
votes

Cela peut ne pas éviter le "masque et déplacer chaque integer" exigence. Je ne suis pas sûr d'éviter les moyens de masque et de décalage dans le contexte des valeurs longues Python.

Les octets sont ceux-ci: xxx

Vous pouvez alors emballer cette liste d'octets en utilisant structure.pack ("16b", octets) < / p>


4 commentaires

"invalide"? Pourriez-vous être plus précis afin que je puisse le réparer?


Il y a une certaine confusion avec les noms de variables ( n vs. code> long_int ). En outre, vous devez probablement utiliser n // = 256 ou n >> = 8 ou n, b = divmod (n, 256) de n / = 256 pour empêcher une boucle (presque) infinie dans Python 3 (ou lorsqu'un flotteur est passé).


@Apalala, @sven Marnach. Merci.


Cela peut probablement sembler plus agréable avec long_int, b = divmod (long_int, 256) :)



9
votes

Je pense que pour les entiers non signés (et ignorer l'endansning) quelque chose comme xxx

peut techniquement satisfer aux exigences de la production spécifique non python, sans utiliser un masque explicite et (je suppose ) n'utilise aucun modules non standard. Pas particulièrement élégant, cependant.


2 commentaires

Cela échoue à une entrée négative: heex (x) retourne -0x123 par exemple.


@Score_under: La toute première phrase indique "pour les entiers non signés".



3
votes

the PYPI Bitarray module en combinaison avec la corbeille bin () Code> La fonction semble être une bonne combinaison pour une solution simple et flexible.

bytes = bitarray(bin(my_long)[2:]).tobytes()


2 commentaires

Fais attention! bin () produit quelque chose comme 0b0101110 , vous devez donc couper le préfixe 0b .


Vous voulez aussi Tobytes () pas tostring () .



2
votes

Pourquoi ne pas utiliser la structure avec le type em> disigne em> disigne deux fois?

import struct
some_file.write(struct.pack("QQ", var/(2**64), var%(2**64)))


0 commentaires

0
votes

Cela peut être un peu tardif, mais je ne vois pas pourquoi vous ne pouvez pas utiliser STRIT:

bigint = 0xFEDCBA9876543210FEDCBA9876543210L
print bigint,hex(bigint).upper()

cbi = struct.pack("!QQ",bigint&0xFFFFFFFFFFFFFFFF,(bigint>>64)&0xFFFFFFFFFFFFFFFF)

print len(cbi)


0 commentaires

1
votes

avec Python 3.2 et plus tard, vous pouvez utiliser int.to_bytes et int.from_bytes : https://docs.python.org/3/library/sttypes.html#int.to_bytes


0 commentaires

0
votes

Basé sur la réponse de @ DSM et supporter des entiers négatifs et des tailles variées d'octets, j'ai créé l'extrait amélioré suivant:

def to_bytes(num, size):
        x = num if num >= 0 else 256**size + num
        h = hex(x)[2:].rstrip("L")
        return binascii.unhexlify("0"*((2*size)-len(h))+h)


0 commentaires