2008-11-30 7 views
6

Existe-t-il une bibliothèque qui convertit des nombres très longs en chaîne en copiant simplement les données?long <-> str conversion binaire

Ces one-liners sont trop lents:

def xlong(s): 
    return sum([ord(c) << e*8 for e,c in enumerate(s)]) 

def xstr(x): 
    return chr(x&255) + xstr(x >> 8) if x else '' 

print xlong('abcd'*1024) % 666 
print xstr(13**666) 

Répondre

4

Vous voulez le module struct.

packed = struct.pack('l', 123456) 
assert struct.unpack('l', packed)[0] == 123456 
+0

Cela ne fonctionnera pas pour les grands nombres, par exemple, 13 ** 666 – jfs

2

Que diriez-vous

from binascii import hexlify, unhexlify 

def xstr(x): 
    hex = '%x' % x 
    return unhexlify('0'*(len(hex)%2) + hex)[::-1] 

def xlong(s): 
    return int(hexlify(s[::-1]), 16) 

Je ne pas le temps, mais il devrait être plus rapide et aussi travailler sur un plus grand nombre, car il n'utilise pas récursivité.

0

Je suppose que vous ne vous souciez pas du format de chaîne, vous voulez juste une sérialisation? Si oui, pourquoi ne pas utiliser le sérialiseur intégré de Python, le module cPickle? La fonction dumps convertira tout objet python incluant un entier long en une chaîne, et la fonction loads est son inverse. Si vous faites cela pour enregistrer dans un fichier, consultez également les fonctions dump et load.

>>> import cPickle 
>>> print cPickle.loads(cPickle.dumps(13**666)) % 666 
73 
>>> print (13**666) % 666 
73 
1

Si vous avez besoin d'une sérialisation rapide, utilisez le module marshal. C'est environ 400 fois plus rapide que vos méthodes.

-1

Performance de cPickle contre marshal (Python 2.5.2, Windows):

python -mtimeit -s"from cPickle import loads,dumps;d=13**666" "loads(dumps(d))" 
1000 loops, best of 3: 600 usec per loop 

python -mtimeit -s"from marshal import loads,dumps;d=13**666" "loads(dumps(d))" 
100000 loops, best of 3: 7.79 usec per loop 

python -mtimeit -s"from pickle import loads,dumps;d= 13**666" "loads(dumps(d))" 
1000 loops, best of 3: 644 usec per loop 

marshal est beaucoup plus rapide.

+6

Seulement si vous l'utilisez naïvement. pickle par défaut à un protocole textuel compatible vers l'arrière. Utilisez cPickle.dumps (d, -1) et les temps deviennent compétitifs: sur ma machine, 4.63 usec/loop pour cPickle vs 3.34 usec/loop pour marshal. –

2

En fait, j'ai un manque de long (s, 256). Je se cachent plus et voir qu'il ya 2 fonctions dans le fichier CAPI Python « longobject.h »:

PyObject * _PyLong_FromByteArray(const unsigned char* bytes, size_t n, int little_endian, int is_signed); 
int _PyLong_AsByteArray(PyLongObject* v, unsigned char* bytes, size_t n, int little_endian, int is_signed); 

Ils font le travail. Je ne sais pas pourquoi il n'y a pas de module python, ou corrigez-moi si je me trompe.

+1

Dans Python3, il existe des méthodes 'int.from_bytes' /' int.to_bytes'. http://docs.python.org/dev/py3k/library/stdtypes.html?highlight=int.from_bytes#int.to_bytes – jfs

Questions connexes