如果lv存储一个long值,并且机器是32位,则代码如下:
iv = int(lv & 0xffffffff)
Run Code Online (Sandbox Code Playgroud)
结果是类型为long的iv,而不是机器的int.
在这种情况下如何获得(带符号)int值?
小智 27
import ctypes
number = lv & 0xFFFFFFFF
signed_number = ctypes.c_long(number).value
Run Code Online (Sandbox Code Playgroud)
Gle*_*ard 14
您正在使用高级脚本语言; 本质上,您运行的系统的本机数据类型不可见.您无法使用此类代码强制转换为本机signed int.
如果您知道要将值转换为32位有符号整数 - 无论平台如何 - 您只需使用简单的数学运算进行转换:
iv = 0xDEADBEEF
if(iv & 0x80000000):
iv = -0x100000000 + iv
Run Code Online (Sandbox Code Playgroud)
本质上,问题是签名从32位扩展到......无限多位,因为Python有任意大的整数.通常情况下,符号扩展是在转换时由CPU指令自动完成的,因此有趣的是,这在Python中比在C中更难,例如C.
通过游戏,我发现了类似于BreizhGatch的功能,但这不需要条件语句.n & 0x80000000提取32位符号位; 然后,-保持相同的32位表示,但对其进行符号扩展; 最后,扩展符号位设置为开n.
def toSigned32(n):
n = n & 0xffffffff
return n | (-(n & 0x80000000))
Run Code Online (Sandbox Code Playgroud)
Bit Twiddling Hacks提出了另一种可能更普遍的解决方案.n ^ 0x80000000翻转32位符号位; 然后- 0x80000000将签署 - 延伸相反的位.另一种思考方式是,最初,负数高于正数(以数字表示0x80000000); 在^交换自己的立场; 然后-将负数转移到0以下.
def toSigned32(n):
n = n & 0xffffffff
return (n ^ 0x80000000) - 0x80000000
Run Code Online (Sandbox Code Playgroud)
小智 8
我可以建议一下:
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)
Run Code Online (Sandbox Code Playgroud)
您可以使用struct library来转换这样的值.这很难看,但有效:
from struct import pack, unpack
signed = unpack('l', pack('L', lv & 0xffffffff))[0]
Run Code Online (Sandbox Code Playgroud)
小智 6
一个快速但肮脏的解决方案(在我的例子中 x 永远不会大于 32 位)。
if x > 0x7fffffff:
x = x - 4294967296
Run Code Online (Sandbox Code Playgroud)