假设我有这个号码i = -6884376
。
我如何将其称为无符号变量?
类似于C中的(unsigned long)i
答案 0 :(得分:70)
<强>假设强>:
(unsigned long)
您表示无符号32位整数然后您只需要将2**32 (or 1 << 32)
添加到负值。
例如,将此应用于-1:
>>> -1
-1
>>> _ + 2**32
4294967295L
>>> bin(_)
'0b11111111111111111111111111111111'
假设#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
C unsigned long
恰好是运行此示例的框上的4个字节。
答案 1 :(得分:52)
要获得相当于C cast的值,只需按位并使用适当的掩码。例如如果unsigned long
是32位:
>>> i = -6884376
>>> i & 0xffffffff
4288082920
或如果它是64位:
>>> i & 0xffffffffffffffff
18446744073702667240
请注意尽管虽然这给了你在C中的值,但它仍然是一个有符号的值,因此任何后续计算都可能给出否定结果,你将不得不继续应用掩码来模拟一个32或64位计算。
这是有效的,因为虽然Python看起来像将所有数字存储为符号和幅度,但按位运算被定义为处理两个补码值。 C以二进制补码存储整数但具有固定位数。 Python按位运算符作用于二进制补码值,但好像它们具有无限数量的位:对于正数,它们用零向左延伸到无穷大,但负数向左延伸用1。 &
运算符会将左边的1字符串更改为零,并且只留下适合C值的位。
以十六进制显示值可能会更清楚(并且我重写为f的字符串作为表达式,表明我们对32位或64位感兴趣):
>>> hex(i)
'-0x690c18'
>>> hex (i & ((1 << 32) - 1))
'0xff96f3e8'
>>> hex (i & ((1 << 64) - 1)
'0xffffffffff96f3e8L'
对于C中的32位值,正数最高可达2147483647(0x7fffffff),负数最高位设置为-1(0xffffffff)至-2147483648(0x80000000)。对于完全适合掩码的值,我们可以通过使用较小的掩码移除符号位然后减去符号位来反转Python中的过程:
>>> u = i & ((1 << 32) - 1)
>>> (u & ((1 << 31) - 1)) - (u & (1 << 31))
-6884376
或64位版本:
>>> u = 18446744073702667240
>>> (u & ((1 << 63) - 1)) - (u & (1 << 63))
-6884376
如果符号位为0,此逆过程将保持值不变,但显然它不是真正的逆,因为如果您开始使用的值不适合掩码大小,则这些位将消失。 / p>
答案 2 :(得分:13)
Python没有内置的无符号类型。您可以使用数学运算来计算表示您将在C中获得的值的 new int,但是没有Python int的“无符号值”。 Python int是整数值的抽象,而不是对固定字节大小整数的直接访问。
答案 3 :(得分:1)
struct
Python内置库: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))
出局:
-11010010000110000011000
4288082920
11111111100101101111001111101000
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)
出局:
-6884376
[注意]:
>
是BigEndian运算。l
很长。L
是无符号的。amd64
体系结构中,int
和long
是32位的,因此可以使用i
和I
代替l
和{{1 }} 分别。 答案 4 :(得分:0)
只需使用abs将python中的未签名转换为已签名
a=-12
b=abs(a)
print(b)
输出: 12
答案 5 :(得分:0)
python没有内置将int转换为unsigned int的内置函数,相反它具有较长的范围。
>>> val = 9223372036854775807 (maximum value of int 64)
>>> type(val)
<type 'int'>
>>> val += 1
>>> type(val)
<type 'long'>
通过将val的值增加1,我超过了有符号64位整数的限制,并且该值转换为long。如果Python使用或转换为无符号整数,则val仍然是int。或者,不长。
有符号整数用一位(通常是最高有效位)表示,对于正数设置为0,对于负数设置为1。 val&0xff实际上是val&0x000000ff(在32位计算机上)。换句话说,将有符号位设置为0,并模拟无符号值。
一个例子:
>>> val = -1
>>> val & 0xff
255
答案 6 :(得分:0)
从3.2版开始:
def toSigned(n, byte_count):
return int.from_bytes(n.to_bytes(byte_count, 'little'), 'little', signed=True)
输出:
In [8]: toSigned(5, 1)
Out[8]: 5
In [9]: toSigned(0xff, 1)
Out[9]: -1