Как получить знаковое целочисленное значение long в python?

Если lv хранит длинное значение, а машина 32 бит, следующий код:

iv = int(lv & 0xffffffff)

выводит iv типа long, а не int.

Как я могу получить (подписанное) значение int в этом случае?

Ответы

Ответ 1

import ctypes

number = lv & 0xFFFFFFFF

signed_number = ctypes.c_long(number).value

Ответ 2

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

Если вы знаете, что хотите преобразовать значение в 32-разрядное целое число со знаком - независимо от платформы - вы можете просто выполнить преобразование с помощью простой математики:

iv = 0xDEADBEEF
if(iv & 0x80000000):
    iv = -0x100000000 + iv

Ответ 3

Могу ли я предложить следующее:

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)

Ответ 4

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

from struct import pack, unpack
signed = unpack('l', pack('L', lv & 0xffffffff))[0]

Ответ 5

По сути, проблема заключается в том, чтобы подписать расширение от 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

Ответ 6

Быстрое и грязное решение (x в моем случае никогда не бывает больше 32-битного).

if x > 0x7fffffff:
    x = x - 4294967296