Эффективная целочисленная упаковка произвольного размера в Python

Вы можете использовать nlargest:

df.apply(lambda x: x.nlargest(25).reset_index(drop=True))

Но я сомневаюсь, что это даст вам много времени честно. Как уже говорилось, вам просто нужно пройти через много данных.

14
задан noamtm 22 April 2009 в 14:36
поделиться

5 ответов

Это немного странно, но вы можете пройти через шестнадцатеричное строковое представление и перейти к двоичному с шестнадцатеричным кодеком:

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

Это немного ломается, потому что шестнадцатеричный кодек требует четного числа цифр, так что вам нужно будет дополнить это, и вам нужно будет установить флаг для обработки отрицательных чисел. Вот типичная упаковка / распаковка:

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

Несмотря на то, что требуются все усилия для заполнения и т. Д., Я не уверен, что это намного лучше, чем ручное решение.

2
ответ дан 1 December 2019 в 13:22
поделиться

Как предложил С.Лотт в комментарии, просто преобразуйте число в строку и упакуйте эту строку. Например,

x = 2 ** 12345
struct.pack("40s", str(x))
0
ответ дан 1 December 2019 в 13:22
поделиться

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

  • 255 или меньше, вы бы использовали только 1 байт
  • 65535 или меньше 2 байта
  • 16777215 или меньше 3 байта
  • и т. д. и т. д.

На Psion PDA они бы обычно есть какая-то схема упаковки, в которой вы читаете первый байт, определяете, установлен ли у него старший бит, а затем читаете другой байт, если он есть. Таким образом, вы будете просто читать байты, пока не прочитаете «полный» номер. Эта система работает достаточно хорошо, если большинство чисел, с которыми вы имеете дело, достаточно малы, поскольку вы обычно будете использовать один или два байта на число.

Альтернатива состоит в том, чтобы один (или более) байтов представлял число общее количество использованных байтов, но в любом случае это в основном строка в Python. то есть это строка из базовых 256 цифр.

2
ответ дан 1 December 2019 в 13:22
поделиться

Предполагается, что постер хочет упаковать большое целое число в виде двоичной строки, т.е. не использовать один байт памяти на цифру в числе. Один из способов сделать это выглядит следующим образом:

import marshal

a = 47L
print marshal.dumps(a)

Это печатает:

'l\x01\x00\x00\x00/\x00'

Я не могу сказать, что я понимаю, как интерпретировать эти биты, прямо сейчас ...

4
ответ дан 1 December 2019 в 13:22
поделиться

Вы имеете в виду что-то примерно так:

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

Что возвращает:

1 01 1
16 10 16
256 0100 256
257 0101 257
1234567890987654321 112210f4b16c1cb1 1234567890987654321

Я просто не уверен, что делать с негативами ... Я не очень хорошо разбираюсь в битах.

РЕДАКТИРОВАТЬ: Другое решение (по моим тестам примерно на 30% быстрее):

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)
5
ответ дан 1 December 2019 в 13:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: