Разделение интервала на 16 битов в два 8 битов ints в Python

Я должен преобразовать данное целое число на 16 битов в два целых числа на 8 битов, которые затем берутся и используются в качестве вывода, куда они направляются, берет два целых числа на 8 битов и повторно комбинирует их как вход на 16 битов (к сожалению, из моего управления). Мои работы решения, но грязные чувства. Для крупного числа я - бит, смещающий исходное число, и для прекрасного числа я смотрю на него по модулю 256.

Таким образом, я должен делать подразделение пола для крупного числа, или я должен брать самые низкие 8 битов для прекрасного числа (и раз так как?)?

Или я - сумасшедшие и использующие два различных метода для разделения числа, не проблема?

def convert(x):
    ''' convert 16 bit int x into two 8 bit ints, coarse and fine.

    '''
    c = x >> 8  # The value of x shifted 8 bits to the right, creating coarse.
    f = x % 256  # The remainder of x / 256, creating fine.
    return c, f
5
задан nrn 26 June 2010 в 09:26
поделиться

6 ответов

Я бы сделал

c = (x >> 8) & 0xff
f = x & 0xff

Это безопаснее, см. например,

>>> (10303 >> 8) & 0xff
40
>>> (1030333333 >> 8) & 0xff
163
>>> (1030333333 >> 8) 
4024739

Поскольку в python вы не можете контролировать, является ли число 16-битным или нет, вы должны принудительно преобразовать его в значение не более 16 бит. Это не нужно, если вы уверены, что у вас будет 16-битное значение, но таким образом функция становится более общей и позволяет вам интересоваться только 16-битными значениями, независимо от того, что содержит контейнер.

13
ответ дан 18 December 2019 в 06:49
поделиться

В Python использование битов не имеет особых преимуществ, поэтому я бы выбрал:

c, f= divmod(your_number, 256)

РЕДАКТИРОВАТЬ: чтобы сделать ваше намерение еще более очевидным для программы просмотра исходного кода, испытывающей затруднения в отношении силы двух (если такая зверь существует), вы можете заменить простой 256 гораздо более красочными альтернативами, например 1 << 8 , 2 ** 8 , 0x100 или 0400 . Сворачивание констант, выполняемое оптимизатором глазка, начиная с версии 2.5, гарантирует, что любой из них точно такой же, как при использовании 256 (я, очевидно, говорю о первых двух альтернативах, которые являются выражениями, которые оцениваются как 256 ; последние два являются константой 256 ).

$ python
Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> dis.dis(compile("c, f= divmod(your_number, 1<<8)", "", "exec"))
  1           0 LOAD_NAME                0 (divmod)
              3 LOAD_NAME                1 (your_number)
              6 LOAD_CONST               3 (256)
              9 CALL_FUNCTION            2
             12 UNPACK_SEQUENCE          2
             15 STORE_NAME               2 (c)
             18 STORE_NAME               3 (f)
             21 LOAD_CONST               2 (None)
             24 RETURN_VALUE
7
ответ дан 18 December 2019 в 06:49
поделиться

Вы говорите, что используете эти числа как выходные данные, что предполагает, что они будут преобразованы в строки в какой-то момент по строке. Имея это в виду, я предлагаю вам взглянуть на модуль struct , который предназначен именно для такого рода вещей (упаковка чисел в строки двоичных данных). В качестве бонуса вы получаете встроенную проверку ошибок для случая, когда x больше 65535 (так что, если в вашей программе что-то ужасно нестабильно, вы получите исключение). Например,

s = struct.pack('>H', x)

эквивалентен

if x > 65535:
    raise struct.error(...)
c, f = convert(x)
s = chr(c) + chr(f) # big-endian (network) byte ordering

. Если вам нужен другой порядок байтов, вы можете написать

s = struct.pack('<H', x)

. Если у вас есть целая группа чисел для одновременного преобразования, struct.pack может выполняйте их группами:

x = [10333, 10475, 3021, ...] # for example
s = struct.pack('>' + 'H' * len(x), *x)
1
ответ дан 18 December 2019 в 06:49
поделиться

Я бы использовал побитовое &, а не%. Вероятно, в наши дни это мало что меняет для коротких целых чисел, но в более широком смысле оператор & потенциально более эффективен.

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

0
ответ дан 18 December 2019 в 06:49
поделиться

Если вы используете две половины числа в разных местах, я бы рекомендовал иметь две отдельные функции, но если вы собираетесь использовать их в одном месте, одна функция будет работать точно так же.

Есть несколько правильных способов разделить число, так что в конечном итоге все сводится к личным предпочтениям. Ваш код будет работать нормально, если вы передадите только числа длиной не более 16 бит. (что, вероятно, не будет большой проблемой, но вы должны знать об этом)

0
ответ дан 18 December 2019 в 06:49
поделиться

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

2
ответ дан 18 December 2019 в 06:49
поделиться
Другие вопросы по тегам:

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