31

如果 lv 存储一个 long 值,并且机器是 32 位,则如下代码:

iv = int(lv & 0xffffffff)

结果是 long 类型的 iv,而不是机器的 int。

在这种情况下,我怎样才能得到(有符号的)int 值?

4

6 回答 6

35
import ctypes

number = lv & 0xFFFFFFFF

signed_number = ctypes.c_long(number).value
于 2012-02-19T17:13:34.500 回答
21

您正在使用高级脚本语言;从本质上讲,您正在运行的系统的本机数据类型是不可见的。您不能使用这样的代码强制转换为本机签名的 int。

如果您知道要将值转换为 32 位有符号整数(无论平台如何),您可以使用简单的数学进行转换:

iv = 0xDEADBEEF
if(iv & 0x80000000):
    iv = -0x100000000 + iv
于 2009-09-03T21:03:04.310 回答
16

本质上,问题是将符号从 32 位扩展到...无限位,因为 Python 具有任意大的整数。通常,符号扩展是由 CPU 指令在强制转换时自动完成的,所以有趣的是,这在 Python 中比在 C 中更难。

通过玩弄,我发现了一些类似于 BreizhGatch 的函数,但它不需要条件语句。n & 0x80000000提取 32 位符号位;然后,-保持相同的 32 位表示,但对其进行符号扩展;最后,扩展符号位设置为 on 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
于 2016-05-08T03:17:02.927 回答
9

我可以建议这个:

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)
于 2012-07-23T12:22:44.607 回答
9

您可以使用struct library 来转换这样的值。这很丑陋,但有效:

from struct import pack, unpack
signed = unpack('l', pack('L', lv & 0xffffffff))[0]
于 2009-09-07T16:53:49.193 回答
4

一个快速而肮脏的解决方案(在我的情况下,x 永远不会大于 32 位)。

if x > 0x7fffffff:
    x = x - 4294967296
于 2016-06-27T22:34:28.467 回答