двоичное преобразование long <-> str - PullRequest
6 голосов
/ 30 ноября 2008

Существует ли библиотека, которая преобразует очень длинные числа в строку, просто копируя данные?

Эти однострочники слишком медленные:

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)

Ответы [ 6 ]

4 голосов
/ 30 ноября 2008

Вы хотите модуль struct.

packed = struct.pack('l', 123456)
assert struct.unpack('l', packed)[0] == 123456
2 голосов
/ 14 декабря 2008

На самом деле у меня не хватает long (с, 256). Я скрываюсь еще и вижу, что в Python CAPI-файле "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);

Они делают работу. Я не знаю, почему они не включены в какой-либо модуль Python, или поправьте меня, если я ошибаюсь.

2 голосов
/ 30 ноября 2008

Как насчет

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)

Я не рассчитал время, но он должен быть быстрее и работать с большими числами, поскольку он не использует рекурсию.

1 голос
/ 30 ноября 2008

Если вам нужна быстрая сериализация, используйте модуль marshal . Это примерно в 400 раз быстрее, чем ваши методы.

0 голосов
/ 30 ноября 2008

Производительность cPickle против 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 намного быстрее.

0 голосов
/ 30 ноября 2008

Полагаю, вас не волнует формат строки, вы просто хотите сериализацию? Если так, то почему бы не использовать встроенный сериализатор Python, модуль cPickle ? Функция dumps преобразует любой объект python, включая длинное целое число, в строку, а функция loads является ее инверсией. Если вы делаете это для сохранения в файл, проверьте функции dump и load.

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