简体   繁体   English

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

[英]How to convert signed to unsigned integer in python

Let's say I have this number i = -6884376 .假设我有这个数字i = -6884376 How do I refer to it as to an unsigned variable?我如何将它称为无符号变量? Something like (unsigned long)i in C.像 C 中的(unsigned long)i类的东西。

Assuming :假设

  1. You have 2's-complement representations in mind;你有 2 的补码表示; and,和,
  2. By (unsigned long) you mean unsigned 32-bit integer,通过(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.例如,如果您有 1 的补码表示,那么您需要应用~前缀运算符。 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"). Python 整数努力给人一种使用无限宽 2 的补码表示的错觉(就像常规 2 的补码,但具有无限数量的“符号位”)。

And to duplicate what the platform C compiler does, you can use the ctypes module:要复制平台 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 long happens to be 4 bytes on the box that ran this sample.在运行此示例的机器上,C 的unsigned long恰好是 4 个字节。

To get the value equivalent to your C cast, just bitwise and with the appropriate mask.要获得与 C 类型转换等效的值,只需按位并使用适当的掩码即可。 eg if unsigned long is 32 bit:例如,如果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.这是有效的,因为尽管 Python 看起来像是将所有数字存储为符号和大小,但按位运算被定义为处理二进制补码值。 C stores integers in twos complement but with a fixed number of bits. C 以二进制补码形式存储整数,但位数固定。 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. Python 按位运算符作用于二进制补码值,但就好像它们有无限数量的位:对于正数,它们向左扩展到无穷大,带零,但负数向左扩展,带 1。 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. &运算符会将向左的 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).对于 C 中的 32 位值,正数最高可达 2147483647 (0x7fffffff),负数的最高位设置为从 -1 (0xffffffff) 到 -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:对于完全适合掩码的值,我们可以通过使用较小的掩码去除符号位然后减去符号位来反转 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,这个逆过程将使值保持不变,但显然它不是真正的逆,因为如果您从一个不适合掩码大小的值开始,那么这些位就消失了。

Python doesn't have builtin unsigned types. Python 没有内置的无符号类型。 You can use mathematical operations to compute a new int representing the value you would get in C, but there is no "unsigned value" of a Python int.您可以使用数学运算来计算一个新的int,该 int 表示您将在 C 中获得的值,但 Python int 没有“无符号值”。 The Python int is an abstraction of an integer value, not a direct access to a fixed-byte-size integer. Python int 是整数值的抽象,而不是对固定字节大小的整数的直接访问。

You could use the struct Python built-in library:您可以使用struct Python 内置库:

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. >是 BigEndian 操作。
  • l is long. l很长
  • L is unsigned long. L是无符号长整型。
  • In amd64 architecture int and long are 32bit, So you could use i and I instead of l and L respectively.amd64架构中intlong是 32 位,所以你可以分别使用iI而不是lL

Since version 3.2 :从 3.2 版开始:

def toSigned(n, byte_count): 
  return int.from_bytes(n.to_bytes(byte_count, 'little'), 'little', signed=True)

output :输出:

In [8]: toSigned(5, 1)                                                                                                                                                                                                                                                                                                     
Out[8]: 5

In [9]: toSigned(0xff, 1)                                                                                                                                                                                                                                                                                                  
Out[9]: -1

just use abs for converting unsigned to signed in python只需使用 abs 将未签名转换为已签名的 python

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

Output: 12输出:12

python does not have any builtin to convert int to unsigned int.Instead it is having long for longer range. python没有任何内置来将int转换为unsigned int.Instead它有更长的范围。

>>> 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. 通过将val的值增加1,我超过了有符号64位整数的限制,并将该值转换为long。 If Python had used or converted to an unsigned integer, val would still have been an int. 如果Python使用或转换为无符号整数,则val仍然是int。 Or, not long. 或者,不久。

Signed integers are represented by a bit, usually the most significant bit, being set to 0 for positive numbers or 1 for negative numbers. 有符号整数由一个位表示,通常是最高位,对于正数设置为0,对于负数设置为1。 What val & 0xff does is actually val & 0x000000ff (on a 32 bit machine). val和0xff实际上是val和0x000000ff(在32位机器上)。 In other words, the signed bit is set to 0 and an unsigned value is emulated. 换句话说,有符号位设置为0,并且模拟无符号值。

An example: 一个例子:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM