На этом шаге мы рассмотрим некоторые методы, которые можно использовать для решения этой задачи.
У вас есть строка байтов, и вам нужно распаковать ее в целочисленное значение. Или же вам нужно конвертировать большое целое число в байтовую строку.
Предположим, ваша программа должна работать с байтовой строкой из 16 элементов, которая содержит 128-битное целочисленное значение. Например:
>>> data = b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004'
>>>
Чтобы перевести байты в целое число, используйте int.from_bytes(), определив порядок следования байтов таким образом:
>>> len(data) 16 >>> int.from_bytes(data, 'little') 69120565665751139577663547927094891008 >>> int.from_bytes(data, 'big') 94522842520747284487117727783387188 >>>
Чтобы преобразовать большое целочисленное значение обратно в байтовую строку, используйте метод int.to_bytes(), определив количество байтов и порядок их следования. Например:
>>> x = 94522842520747284487117727783387188 >>> x.to_bytes(16, 'big') b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004' >>> x.to_bytes(16, 'little') b'4\x00#\x00\x01\xef\xcd\x00\xab\x90x\x00V4\x12\x00' >>>
Преобразование больших целочисленных значений из и в байтовые строки - не самая обычная операция. Однако иногда такая задача возникает в областях типа криптографии или работы с сетью. Например, сетевые адреса IPv6 представлены 128-битными целыми числами. Если вы пишете программу, в которой нужно вытягивать такие значения из данных, то можете столкнуться с этой задачей.
В качестве альтернативы вы можете попытаться распаковывать значения, используя модуль struct. Это работает, но размер целых чисел, которые могут быть распакованы с помощью struct, ограничен. Поэтому вам понадобится распаковывать несколько значений и объединять их для создания итогового значения. Например:
>>> data b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004' >>> import struct >>> hi, lo = struct.unpack('>QQ', data) >>> (hi << 64) + lo 94522842520747284487117727783387188 >>>
Определение порядка следования байтов (little или big) просто указывает, записаны ли байты, из которых составляется целое число, в порядке от старшего к младшему или наоборот. Это легко понять, рассмотрев пример такого специально составленного шестнадцатеричного значения:
>>> x = 0x01020304 >>> x.to_bytes(4, 'big') b'\x01\x02\x03\x04' >>> x.to_bytes(4, 'little') b'\x04\x03\x02\x01' >>>
Если вы хотите упаковать целое число в строку байтов, но оно не поместится, вы получите ошибку. При необходимости вы можете использовать метод int.bit_ length(), чтобы определить, сколько байтов потребуется для хранения значения:
>>> x = 523 ** 23 >>> x 335381300113661875107536852714019056160355655333978849017944067 >>> x.to_bytes(16, 'little') Traceback (most recent call last): . . . . OverflowError: int too big to convert >>> x.bit_length() 208 >>> nbytes, rem = divmod(x.bit_length(), 8) >>> if rem: nbytes += 1 >>> x.to_bytes(nbytes, 'little') b'\x03X\xf1\x82iT\x96\xac\xc7c\x16\xf3\xb9\xcf\x18\xee\xec\x91\xd1\x98\xa2\xc8\xd9R\xb5\xd0' >>>
На следующем шаге мы рассмотрим вычисления с комплексными числами.