Ответ 1
import ctypes
number = lv & 0xFFFFFFFF
signed_number = ctypes.c_long(number).value
Если lv хранит длинное значение, а машина 32 бит, следующий код:
iv = int(lv & 0xffffffff)
выводит iv типа long, а не int.
Как я могу получить (подписанное) значение int в этом случае?
import ctypes
number = lv & 0xFFFFFFFF
signed_number = ctypes.c_long(number).value
Вы работаете на высокоуровневом языке сценариев; по своей природе, собственные типы данных используемой системы не отображаются. Вы не можете отнести к встроенному подписанному int с таким кодом.
Если вы знаете, что хотите преобразовать значение в 32-разрядное целое число со знаком - независимо от платформы - вы можете просто выполнить преобразование с помощью простой математики:
iv = 0xDEADBEEF
if(iv & 0x80000000):
iv = -0x100000000 + iv
Могу ли я предложить следующее:
def getSignedNumber(number, bitLength):
mask = (2 ** bitLength) - 1
if number & (1 << (bitLength - 1)):
return number | ~mask
else:
return number & mask
print iv, '->', getSignedNumber(iv, 32)
Вы можете использовать библиотеку struct для преобразования значений, подобных этому. Это уродливо, но работает:
from struct import pack, unpack
signed = unpack('l', pack('L', lv & 0xffffffff))[0]
По сути, проблема заключается в том, чтобы подписать расширение от 32 бит до... бесконечного числа бит, потому что у Python есть сколь угодно большие целые числа. Обычно расширение знака выполняется автоматически с помощью инструкций ЦП при кастинге, поэтому интересно, что это сложнее в Python, чем в, скажем, в C.
Играя вокруг, я нашел нечто похожее на функцию BreizhGatch, но это не требует условного оператора. n & 0x80000000
извлекает 32-битовый бит знака; то -
хранит одно и то же 32-битное представление, но расширяет его; наконец, расширенные знаковые биты устанавливаются на n
.
def toSigned32(n):
n = n & 0xffffffff
return n | (-(n & 0x80000000))
Bit Twiddling Hacks предлагает другое решение, которое, возможно, работает в более общем плане. n ^ 0x80000000
переворачивает 32-битовый бит знака; то - 0x80000000
будет подписывать - увеличивать противоположный бит. Другой способ подумать об этом состоит в том, что изначально отрицательные числа выше положительных чисел (разделены на 0x80000000
); ^
меняет свои позиции; то -
сдвигает отрицательные числа до 0.
def toSigned32(n):
n = n & 0xffffffff
return (n ^ 0x80000000) - 0x80000000
Быстрое и грязное решение (x в моем случае никогда не бывает больше 32-битного).
if x > 0x7fffffff:
x = x - 4294967296