преобразовать символ ascii в 8-битный целочисленный Python со знаком

Кажется, это должно быть очень просто, но я не смог найти ответа ...

В сценарии python я читаю данные с USB-устройства (движения USB-мыши по осям x и y). он поступает в виде отдельных символов ASCII. Я легко могу преобразовать в целые числа без знака (0–255) с помощью ord. Но я бы хотел, чтобы это были целые числа со знаком (от -128 до 127) - как я могу это сделать?

Любая помощь очень ценится! Большое спасибо.


person user2477784    schedule 12.06.2013    source источник


Ответы (5)


Вычтите 256, если больше 127:

unsigned = ord(character)
signed = unsigned - 256 if unsigned > 127 else unsigned

В качестве альтернативы перепакуйте байт с помощью модуля struct:

from struct import pack, unpack
signed = unpack('B', pack('b', unsigned))[0]

или прямо от персонажа:

signed = unpack('B', character)[0]
person Martijn Pieters    schedule 12.06.2013

from ctypes import c_int8
value = c_int8(191).value

используйте ctypes со своим значением ord () - в этом случае должно быть -65

бывший. из строковых данных

from ctypes import c_int8
data ='BF'
value1 = int(data, 16) # or ord(data.decode('hex'))
value2 = c_int8(value1).value

value1 - это 16-битное целочисленное представление шестнадцатеричного 'BF', а value2 - 8-битное представление

person Michal Szczepanski    schedule 31.12.2015
comment
Знаковое целочисленное переполнение не определено в C, поэтому это не всегда работает (но, вероятно, будет во всех версиях CPython) - person Artyer; 19.12.2018

Я знаю, что это старый вопрос, но нигде я не нашел удовлетворительного ответа.

Вы можете использовать модуль массива (с дополнительным удобством, что он преобразует полные буферы):

from array import array

buf = b'\x00\x01\xff\xfe'
print(array('b', buf))

# result: array('b', [0, 1, -1, -2])
person Marc    schedule 27.09.2017

Используйте эту функцию, чтобы получить 8-битное целое число со знаком

def to8bitSigned(num): 
    mask7 = 128 #Check 8th bit ~ 2^8
    mask2s = 127 # Keep first 7 bits
    if (mask7 & num == 128): #Check Sign (8th bit)
        num = -((~int(num) + 1) & mask2s) #2's complement
    return num
person Christos Kyprianou    schedule 08.10.2017

Чтобы преобразовать любые входные байты в целые числа со знаком:

def signed8bit_to_int(input):
    (((input >> 7) * 128) ^ input) - ((input >> 7) * 128)

Examples:
signed8bit_to_int(0xc0) = -64
signed8bit_to_int(0xbf) = -65
signed8bit_to_int(0x0f) = 15

Объяснение на примере 0xC0:

  • 0xc0 '0b1100 0000', его последний бит равен 1, что означает, что это байт со знаком
  • шаг 1: проверка на бит со знаком: (((input >> 7) * 128)
  • шаг 2: если это бит со знаком, инвертируйте входные биты:
    от: 100 0000 до 0111 1111 (63 по основанию 10)
  • шаг 3: преобразовать вышеуказанное, обосновав 128: 63 - 128 = -65
person user97662    schedule 25.05.2020