如何在python中获取long的有符号整数值?

23 python unsigned signed

如果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)

  • 我通常不会花时间评论评论,但我强烈不同意 @Bachsau 在这里。我现在正在编写一些(基本上)“丢弃”代码,以从生成 14 位有符号值的设备中采样一堆传感器数据。我只是使用 `ctypes` 将接收到的值符号扩展为 `ctypes.c_short`。我们已经在我们的产品中使用了 C++ 代码来执行此操作,因此将其“移植”到 `ctypes` 是微不足道的。一旦生命周期测试完成,没有人会再次关心这个脚本。为什么要 bash `ctypes`?它对各种系统编程任务非常有用! (5认同)
  • 如果可行的话,这不是一个坏的解决方案。有时,如果您知道自己在做什么,那么能够深入研究并调整一些低级的东西是件好事。这比其他一些同样需要位移的低级方法要明确得多。 (2认同)
  • 使用 `ctypes.c_int32` 而不是 `c_long` 以确保所有平台上的 32 位。 (2认同)

Gle*_*ard 14

您正在使用高级脚本语言; 本质上,您运行的系统的本机数据类型不可见.您无法使用此类代码强制转换为本机signed int.

如果您知道要将值转换为32位有符号整数 - 无论平台如何 - 您只需使用简单的数学运算进行转换:

iv = 0xDEADBEEF
if(iv & 0x80000000):
    iv = -0x100000000 + iv
Run Code Online (Sandbox Code Playgroud)

  • SamB:对于这个问题(正如我所解释的那样 - OP从来没有做过回应的礼貌),它就像这种转换一样简洁直接.它比结构更清晰,更明显.当然,它应该仍然隐藏在一个函数中并记录下来. (2认同)
  • 这个答案可以像一样单行化:`iv - =(iv&0x80000000)<< 1` (2认同)

gen*_*kev 9

本质上,问题是签名从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)

  • +1 表示不使用条件。它在 Python 中可能没有太大的不同,但它确实让人感觉更令人满意。 (3认同)

小智 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)


Tup*_*teq 6

您可以使用struct library来转换这样的值.这很难看,但有效:

from struct import pack, unpack
signed = unpack('l', pack('L', lv & 0xffffffff))[0]
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用订单/尺寸/对齐字符之一,则可以将其设为便携式.例如,使用`'= l'`和`'= L'`作为格式字符串. (3认同)

小智 6

一个快速但肮脏的解决方案(在我的例子中 x 永远不会大于 32 位)。

if x > 0x7fffffff:
    x = x - 4294967296
Run Code Online (Sandbox Code Playgroud)