Эндиантность целых чисел в Python

Я работаю над программой, где храню некоторые данные в целых числах и обрабатываю их поразрядным образом. Например, я могу получить число 48, которое я буду обрабатывать поэтапно. В целом, конечность целых чисел зависит от машинного представления целых чисел, но делает ли Python что-либо, чтобы гарантировать, что ints всегда будет мало-endian? Или мне нужно проверить соответствие, как я бы на C, а затем написать отдельный код для двух случаев?

Я спрашиваю, потому что мой код работает на машине Sun, и, хотя тот, на котором он работает, теперь использует процессоры Intel, мне, возможно, придется переключиться на машину с процессорами Sun в будущем, и я знаю, что это big-endian.

Ответы

Ответ 1

Python int имеет ту же конечность, что и процессор, над которым он работает. Модуль struct позволяет конвертировать байтовые капли в ints (и наоборот, и некоторые другие типы данных тоже) как в native, little-endian, или big-endian способами, в зависимости от строка формата, которую вы выбираете: запустите формат с помощью @ или нет символа энтитичности, чтобы использовать встроенную endianness (и собственные размеры - все остальное использует стандартные размеры), '~' для native, '<' для little-endian, ' > ' или '!' для больших стран.

Это байтовое число, а не побитовое; не уверен точно, что вы подразумеваете под побитовой обработкой в ​​этом контексте, но я предполагаю, что он может быть размещен аналогичным образом.

Для быстрой "массовой" обработки в простых случаях рассмотрите также модуль array - методы fromstring и tostring может работать на большом количестве байтов быстро, а метод byteswap может получить вас "другой" endianness (родной для не-native или наоборот), снова быстро и для большого количества элементов (весь массив).

Ответ 2

Если вам нужно обработать ваши данные "поразмерно", вам может помочь bitstring. Он также может иметь дело с контентом между платформами (по крайней мере, по последнему строчку сборки), которые будут выпущены в ближайшие несколько дней.

Модуль struct является наилучшим стандартным методом решения проблем между платформами. Например, пакеты упаковывают и распаковывают целые числа 1, 2, 3 на два "коротких" и один "длинный" (2 и 4 байта на большинстве платформ), используя собственную энтитичность:

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)

Чтобы программно определить консистенцию платформы, вы можете использовать

>>> import sys
>>> sys.byteorder

который либо вернет "big", либо "little".

Ответ 3

Проверить, когда?

При выполнении побитовых операций int in будет иметь такую ​​же endianess, что и введенные вами int. Вам не нужно это проверять. Вам нужно только об этом заботиться при преобразовании в/из последовательностей байтов на обоих языках, afaik.

В Python для этого используется структурный модуль, чаще всего struct.pack() и struct.unpack().

Ответ 4

Следующий фрагмент скажет вам, является ли ваш системный по умолчанию малозначимым (в противном случае это big-endian)

import struct
little_endian = (struct.unpack('<I', struct.pack('=I', 1))[0] == 1)

Обратите внимание, что это не повлияет на поведение побитовых операторов: 1<<1 равно 2, независимо от стандартности по умолчанию вашей системы.