如何在python中将signed转换为无符号整数

Lio*_*ior 64 python unsigned signed integer

假设我有这个号码i = -6884376.我如何将其称为无符号变量?像(unsigned long)iC中的东西

Tim*_*ers 81

假设:

  1. 你有2个补码表示; 和,
  2. 通过(unsigned long)的意思是 32位无符号整数,

那么你只需要添加2**32 (or 1 << 32)负值.

例如,将此应用于-1:

>>> -1
-1
>>> _ + 2**32
4294967295L
>>> bin(_)
'0b11111111111111111111111111111111'
Run Code Online (Sandbox Code Playgroud)

假设#1表示您希望-1被视为1位的实心字符串,假设#2表示您需要其中的32位.

但是,没有人可以说出你隐藏的假设是什么.例如,如果您考虑到1的补码表示,则需要应用~前缀运算符.Python整数努力工作以给出使用无限宽2的补码表示的假象(如常规2的补码,但具有无限数量的"符号位").

要复制平台C编译器的功能,您可以使用以下ctypes模块:

>>> import ctypes
>>> ctypes.c_ulong(-1)  # stuff Python's -1 into a C unsigned long
c_ulong(4294967295L)
>>> _.value
4294967295L
Run Code Online (Sandbox Code Playgroud)

unsigned long在运行此示例的框中,C 恰好是4个字节.

  • 我不知道你可以使用`_`来引用前一行的结果! (17认同)
  • @HelloGoodbye,使用“_”来检索先前的结果不是语言本身的功能,而是一些(大多数?全部?)交互式Python shell实现的便利。无论如何,他们必须获取最新的结果才能显示。语言本身不做这样的事情。 (2认同)

Dun*_*can 58

要获得相当于C cast的值,只需按位并使用适当的掩码.例如,如果unsigned long是32位:

>>> i = -6884376
>>> i & 0xffffffff
4288082920
Run Code Online (Sandbox Code Playgroud)

或者如果它是64位:

>>> i & 0xffffffffffffffff
18446744073702667240
Run Code Online (Sandbox Code Playgroud)

请注意,虽然这给了你在C中的值,它仍然是一个有符号的值,因此任何后续计算都可能给出否定结果,你将不得不继续应用掩码来模拟32或64位计算.

这是有效的,因为虽然Python看起来像将所有数字存储为符号和大小,但按位运算被定义为处理两个补码值.C以二进制补码存储整数但具有固定位数.Python按位运算符作用于二进制补码值,但好像它们具有无限数量的位:对于正数,它们用零向左延伸到无穷大,但负数向左延伸用1.该&运营商将改变那些那向左串入零和离开你只是必须装配到C值的位.

以十六进制显示值可以使这更清楚(并且我重写为f的字符串作为表达式以表明我们对32位或64位感兴趣):

>>> hex(i)
'-0x690c18'
>>> hex (i & ((1 << 32) - 1))
'0xff96f3e8'
>>> hex (i & ((1 << 64) - 1)
'0xffffffffff96f3e8L'
Run Code Online (Sandbox Code Playgroud)

对于C中的32位值,正数最高为2147483647(0x7fffffff),负数最高位设置为-1(0xffffffff)至-2147483648(0x80000000).对于完全适合掩码的值,我们可以通过使用较小的掩码删除符号位然后减去符号位来反转Python中的过程:

>>> u = i & ((1 << 32) - 1)
>>> (u & ((1 << 31) - 1)) - (u & (1 << 31))
-6884376
Run Code Online (Sandbox Code Playgroud)

或者对于64位版本:

>>> u = 18446744073702667240
>>> (u & ((1 << 63) - 1)) - (u & (1 << 63))
-6884376
Run Code Online (Sandbox Code Playgroud)

如果符号位为0,则此逆过程将保持值不变,但显然它不是真正的逆,因为如果您开始使用的值不适合掩码大小,则这些位将消失.

  • 这到底为什么有效?(以及逆运算是什么) (2认同)
  • @MB我扩展了答案,希望能对您有所帮助。 (2认同)

hl0*_*37_ 14

从 3.2 版本开始:

\n
def unsignedToSigned(n, byte_count): \n  return int.from_bytes(n.to_bytes(byte_count, 'little', signed=False), 'little', signed=True)\n\ndef signedToUnsigned(n, byte_count): \n  return int.from_bytes(n.to_bytes(byte_count, 'little', signed=True), 'little', signed=False)\n
Run Code Online (Sandbox Code Playgroud)\n

输出 :

\n
In [3]: unsignedToSigned(5, 1)\nOut[3]: 5\n\nIn [4]: signedToUnsigned(5, 1)\nOut[4]: 5\n\nIn [5]: unsignedToSigned(0xFF, 1)\nOut[5]: -1\n\nIn [6]: signedToUnsigned(0xFF, 1)\n---------------------------------------------------------------------------\nOverflowError                             Traceback (most recent call last)\nInput In [6], in <cell line: 1>()\n----> 1 signedToUnsigned(0xFF, 1)\n\nInput In [1], in signedToUnsigned(n, byte_count)\n      4 def signedToUnsigned(n, byte_count): \n----> 5   return int.from_bytes(n.to_bytes(byte_count, 'little', signed=True), 'little', signed=False)\n\nOverflowError: int too big to convert\n\nIn [7]: signedToUnsigned(-1, 1)\nOut[7]: 255\n
Run Code Online (Sandbox Code Playgroud)\n

说明:to/from_bytes 与字节之间进行转换,以 2 的补码形式将数字视为大小位之一byte_count * 8。在 C/C++ 中,您可能应该分别传递48作为byte_count32 或 64 位数字(类型int)。\n我首先将输入数字按照其应有的格式打包(使用signed参数来控制有符号/无符号) ),然后解压为我们希望的格式。你就得到了结果。

\n

请注意尝试使用比表示数字所需的字节数少的字节 ( In [6]) 时的异常。0xFF 是 255,无法使用 C 类型表示char(-128 \xe2\x89\xa4 n \xe2\x89\xa4 127)。这比任何其他行为都更好。

\n


Bre*_*arn 13

Python没有内置的无符号类型.您可以使用数学运算来计算表示您将在C中获得的值的 int,但是没有Python int的"无符号值".Python int是整数值的抽象,而不是对固定字节大小整数的直接访问.


Ben*_*ari 6

您可以使用structPython 内置库:

编码:

import struct

i = -6884376
print('{0:b}'.format(i))

packed = struct.pack('>l', i)  # Packing a long number.
unpacked = struct.unpack('>L', packed)[0]  # Unpacking a packed long number to unsigned long
print(unpacked)
print('{0:b}'.format(unpacked))
Run Code Online (Sandbox Code Playgroud)

出去:

-11010010000110000011000
4288082920
11111111100101101111001111101000
Run Code Online (Sandbox Code Playgroud)

解码:

dec_pack = struct.pack('>L', unpacked)  # Packing an unsigned long number.
dec_unpack = struct.unpack('>l', dec_pack)[0]  # Unpacking a packed unsigned long number to long (revert action).
print(dec_unpack)
Run Code Online (Sandbox Code Playgroud)

出去:

-6884376
Run Code Online (Sandbox Code Playgroud)

[注意]:

  • > 是 BigEndian 操作。
  • l 长。
  • L 是无符号长。
  • amd64体系结构中,intandlong是 32 位,因此您可以分别使用iandI代替land L