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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20766813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 21:10:18  来源:igfitidea点击:

How to convert signed to unsigned integer in python

pythonintegerunsignedsigned

提问by Lior

Let's say I have this number i = -6884376. How do I refer to it as to an unsigned variable? Something like (unsigned long)iin C.

假设我有这个号码i = -6884376。我如何将它称为无符号变量?类似于(unsigned long)iC 中的东西。

采纳答案by Tim Peters

Assuming:

假设

  1. You have 2's-complement representations in mind; and,
  2. By (unsigned long)you meanunsigned 32-bit integer,
  1. 你有 2 的补码表示;和,
  2. 通过(unsigned long)的意思是32位无符号整数,

then you just need to add 2**32 (or 1 << 32)to the negative value.

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

For example, apply this to -1:

例如,将其应用于 -1:

>>> -1
-1
>>> _ + 2**32
4294967295L
>>> bin(_)
'0b11111111111111111111111111111111'

Assumption #1 means you want -1 to be viewed as a solid string of 1 bits, and assumption #2 means you want 32 of them.

假设 #1 意味着您希望 -1 被视为 1 位的实心字符串,假设 #2 意味着您想要其中的 32 个。

Nobody but you can say what your hidden assumptions are, though. If, for example, you have 1's-complement representations in mind, then you need to apply the ~prefix operator instead. Python integers work hard to give the illusion of using an infinitely wide 2's complement representation (like regular 2's complement, but with an infinite number of "sign bits").

但是,除了您之外,没有人可以说出您隐藏的假设是什么。例如,如果您有 1 的补码表示,那么您需要改为应用~前缀运算符。Python 整数努力给人一种使用无限宽 2 的补码表示的错觉(就像常规 2 的补码,但具有无限数量的“符号位”)。

And to duplicate what the platform C compiler does, you can use the ctypesmodule:

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

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

C's unsigned longhappens to be 4 bytes on the box that ran this sample.

Cunsigned long恰好是运行此示例的机器上的 4 个字节。

回答by BrenBarn

Python doesn't have builtin unsigned types. You can use mathematical operations to compute a newint representing the value you would get in C, but there is no "unsigned value" of a Python int. The Python int is an abstraction of an integer value, not a direct access to a fixed-byte-size integer.

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

回答by Duncan

To get the value equivalent to your C cast, just bitwise and with the appropriate mask. e.g. if unsigned longis 32 bit:

要获得与 C 类型转换等效的值,只需按位并使用适当的掩码即可。例如,如果unsigned long是 32 位:

>>> i = -6884376
>>> i & 0xffffffff
4288082920

or if it is 64 bit:

或者如果是 64 位:

>>> i & 0xffffffffffffffff
18446744073702667240

Do be aware though that although that gives you the value you would have in C, it is still a signed value, so any subsequent calculations may give a negative result and you'll have to continue to apply the mask to simulate a 32 or 64 bit calculation.

请注意,虽然这为您提供了 C 中的值,但它仍然是一个带符号的值,因此任何后续计算都可能给出负结果,您必须继续应用掩码来模拟 32 或 64位计算。

This works because although Python looks like it stores all numbers as sign and magnitude, the bitwise operations are defined as working on two's complement values. C stores integers in twos complement but with a fixed number of bits. Python bitwise operators act on twos complement values but as though they had an infinite number of bits: for positive numbers they extend leftwards to infinity with zeros, but negative numbers extend left with ones. The &operator will change that leftward string of ones into zeros and leave you with just the bits that would have fit into the C value.

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

Displaying the values in hex may make this clearer (and I rewrote to string of f's as an expression to show we are interested in either 32 or 64 bits):

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

>>> hex(i)
'-0x690c18'
>>> hex (i & ((1 << 32) - 1))
'0xff96f3e8'
>>> hex (i & ((1 << 64) - 1)
'0xffffffffff96f3e8L'

For a 32 bit value in C, positive numbers go up to 2147483647 (0x7fffffff), and negative numbers have the top bit set going from -1 (0xffffffff) down to -2147483648 (0x80000000). For values that fit entirely in the mask, we can reverse the process in Python by using a smaller mask to remove the sign bit and then subtracting the sign bit:

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

>>> u = i & ((1 << 32) - 1)
>>> (u & ((1 << 31) - 1)) - (u & (1 << 31))
-6884376

Or for the 64 bit version:

或者对于 64 位版本:

>>> u = 18446744073702667240
>>> (u & ((1 << 63) - 1)) - (u & (1 << 63))
-6884376

This inverse process will leave the value unchanged if the sign bit is 0, but obviously it isn't a true inverse because if you started with a value that wouldn't fit within the mask size then those bits are gone.

如果符号位为 0,这个逆过程将使值保持不变,但显然它不是真正的逆,因为如果您从一个不适合掩码大小的值开始,那么这些位就消失了。

回答by Hari Prasath

just use abs for converting unsigned to signed in python

只需使用 abs 将未签名转换为已签名的 python

 a=-12
b=abs(a)
print(b)

Output: 12

输出:12

回答by Benyamin Jafari

You could use the structPython built-in library:

您可以使用structPython 内置库:

Encode:

编码:

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

Out:

出去:

-11010010000110000011000
4288082920
11111111100101101111001111101000


Decode:

解码:

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)

Out:

出去:

-6884376


[NOTE]:

[注意]:

  • >is BigEndian operation.
  • lis long.
  • Lis unsigned long.
  • In amd64architecture intand longare 32bit, So you could use iand Iinstead of land Lrespectively.
  • >是 BigEndian 操作。
  • l长。
  • L是无符号长。
  • amd64体系结构中,intandlong是 32 位,因此您可以分别使用iandI代替land L

回答by Preeti Duhan

python does not have any builtin to convert int to unsigned int.Instead it is having long for longer range.

python 没有任何内置函数将 int 转换为 unsigned int。相反,它具有更长的范围。

>>> val = 9223372036854775807 (maximum value of int 64)
>>> type(val)
<type 'int'>
>>> val += 1
>>> type(val)
<type 'long'>

By increasing the value of val by 1, I exceed the limit of a signed 64 bit integer and the value is converted to a long. If Python had used or converted to an unsigned integer, val would still have been an int. Or, not long.

通过将 val 的值增加 1,我超过了有符号 64 位整数的限制,并且该值被转换为 long。如果 Python 已使用或转换为无符号整数,则 val 仍将是 int。或者,没多久。

Signed integers are represented by a bit, usually the most significant bit, being set to 0 for positive numbers or 1 for negative numbers. What val & 0xff does is actually val & 0x000000ff (on a 32 bit machine). In other words, the signed bit is set to 0 and an unsigned value is emulated.

有符号整数由一位表示,通常是最高有效位,正数设置为 0,负数设置为 1。val & 0xff 实际上是 val & 0x000000ff (在 32 位机器上)。换句话说,有符号位设置为 0,并模拟无符号值。

An example:

一个例子:

>>> val = -1
>>> val & 0xff
255