Let's say I have this number i = 6884376
.
How do I refer to it as to an unsigned variable?
Something like (unsigned long)i
in C.
 5,841
 9
 32
 46

12Python doesn't have builtin unsigned types. – BrenBarn Dec 24 '13 at 21:16

2you can use abs() function. – Ali SAID OMAR Dec 24 '13 at 21:18

You can probably do something with the `struct` library, but like BrenBarn said; Python doesn't separate signedness. – Dec 24 '13 at 21:18

2Also, what is the problem you're trying to solve by doing this? – BrenBarn Dec 24 '13 at 21:20

@saidomar no, it won't give me the unsigned value, but the absolute value. – Lior Dec 24 '13 at 21:22

@BrenBarn I'm doing some kind of calculation that gives me a negative value, but I want the unsigned representation. – Lior Dec 24 '13 at 21:22

1Python’s integer type has an unlimited precision and is not dependent on underlying fixed size types. As such, it cannot differentiate between unsigned and signed types. You will have to do the conversion yourself. – poke Dec 24 '13 at 21:23

@poke How do I do it by myself? – Lior Dec 24 '13 at 21:23

1What is it you mean by "I want the unsigned representation?" In your example, what do you expect the result to be? – Pandu Dec 24 '13 at 21:25

Do `i = int(str(i).lstrip(''))`. Boo, you've got unsigned `i`!! :D – Shravan Jan 27 '16 at 16:57

1It might be worth noting that whilst pythons int is not signed / unsigned and has unlimited precision, Python itself does in places understand the difference between signed and unsigned integers, for example in array.array. @ThePeacefulCoder  your solution will change the data, i.e. a byte which has been misinterpreted you have just removed a bit. – Jmons Sep 28 '16 at 11:15

9@AliSAIDOMAR no, `abs` function doesn't give what `(unsigned)` cast gives you in C, which is `(uint32_t)a = (1LL << 32)  a` for 2's complement – phuclv Mar 24 '17 at 13:46
6 Answers
Assuming:
 You have 2'scomplement representations in mind; and,
 By
(unsigned long)
you mean unsigned 32bit integer,
then you just need to add 2**32 (or 1 << 32)
to the negative value.
For example, apply this to 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.
Nobody but you can say what your hidden assumptions are, though. If, for example, you have 1'scomplement 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").
And to duplicate what the platform C compiler does, you can use the ctypes
module:
>>> 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.
 67,464
 13
 126
 132

95I didn't know you could use `_` to refer to the result of the previous line! – Yay295 Aug 02 '18 at 00:58

@Yay295 Right! Is this only possible in interactive mode or can it be used in non´interactive mode as well? – HelloGoodbye Oct 12 '20 at 16:22

7@HelloGoodbye, using `"_"` to retrieve a previous result is not a feature of the language itself, but a convenience implemented by some (most? all?) interactive Python shells. They have to grab the most recent result regardless, in order to display it. The language itself does no such thing. – Tim Peters Oct 12 '20 at 17:03

1Just in case anyone else stumbles on this answer I recommend checking out [@Duncan's answer instead](https://stackoverflow.com/a/20766900/1609514) which will convert any Python integer into an `unsigned long` equivalent. Simply adding 2**32 or 1 << 32 only works with negative integers in a certain range I think. – Bill Jan 02 '21 at 01:36

1@Bill, I nevertheless prefer this answer. The answer you linked to hides the likely error if the bits masked away aren't all (a conceptually infinite string of copies of) the sign bit. The answer here leaves a goofylooking result in goofy cases ;) For example, `1000000 & 0xff` returns 192, leaving no clue that information was lost (the result always fits in 8 bits). But `1000000 + 256` returns 999744, a clear clue that something went wrong if you assumed no meaningful bits would be lost. YMMV. – Tim Peters Jan 17 '21 at 20:50
To get the value equivalent to your C cast, just bitwise and with the appropriate mask. e.g. if unsigned long
is 32 bit:
>>> i = 6884376
>>> i & 0xffffffff
4288082920
or if it is 64 bit:
>>> 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.
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.
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):
>>> 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:
>>> u = i & ((1 << 32)  1)
>>> (u & ((1 << 31)  1))  (u & (1 << 31))
6884376
Or for the 64 bit version:
>>> 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.
 92,073
 11
 122
 156


2

3

The inverse has proven quite useful. Some python libraries writeen in C return a signed 64bit value and this ends up as a long in python – user1978816 Nov 11 '19 at 13:09
Python doesn't have builtin unsigned types. 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. The Python int is an abstraction of an integer value, not a direct access to a fixedbytesize integer.
 242,874
 37
 412
 384
Since version 3.2 :
def unsignedToSigned(n, byte_count):
return int.from_bytes(n.to_bytes(byte_count, 'little', signed=False), 'little', signed=True)
def signedToUnsigned(n, byte_count):
return int.from_bytes(n.to_bytes(byte_count, 'little', signed=True), 'little', signed=False)
output :
In [3]: unsignedToSigned(5, 1)
Out[3]: 5
In [4]: signedToUnsigned(5, 1)
Out[4]: 5
In [5]: unsignedToSigned(0xFF, 1)
Out[5]: 1
In [6]: signedToUnsigned(0xFF, 1)

OverflowError Traceback (most recent call last)
Input In [6], in <cell line: 1>()
> 1 signedToUnsigned(0xFF, 1)
Input In [1], in signedToUnsigned(n, byte_count)
4 def signedToUnsigned(n, byte_count):
> 5 return int.from_bytes(n.to_bytes(byte_count, 'little', signed=True), 'little', signed=False)
OverflowError: int too big to convert
In [7]: signedToUnsigned(1, 1)
Out[7]: 255
Explanations : to/from_bytes convert to/from bytes, in 2's complement considering the number as one of size byte_count * 8
bits. In C/C++, chances are you should pass 4
or 8
as byte_count
for respectively a 32 or 64 bit number (the int
type).
I first pack the input number in the format it is supposed to be from (using the signed
argument to control signed/unsigned), then unpack to the format we would like it to have been from. And you get the result.
Note the Exception when trying to use fewer bytes than required to represent the number (In [6]
). 0xFF is 255 which can't be represented using a C's char
type (128 ≤ n ≤ 127). This is preferable to any other behavior.
 3,520
 1
 27
 58

1To me this is by far the most pythonic approach. It even allows for beginner friendly byte packing/unpacking and does check the input, if it is even representable with a given amount of bytes and much more. See https://docs.python.org/3/library/stdtypes.html int.from_bytes and int.to_bytes for more. – XIII_ Nov 10 '21 at 18:44
You could use the struct
Python builtin library:
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.l
is long.L
is unsigned long. In
amd64
architectureint
andlong
are 32bit, So you could usei
andI
instead ofl
andL
respectively.
[UPDATE]
According to the @hl037_ comment, this approach works on int32 not int64 or int128 as I used long operation into struct.pack()
. Nevertheless, in the case of int64, the written code would be changed simply using long long operand (q
) in struct
as follows:
Encode:
i = 9223372036854775807 # the largest int64 number
packed = struct.pack('>q', i) # Packing an int64 number
unpacked = struct.unpack('>Q', packed)[0] # Unpacking signed to unsigned
print(unpacked)
print('{0:b}'.format(unpacked))
Out:
9223372036854775807
111111111111111111111111111111111111111111111111111111111111111
Next, follow the same way for the decoding stage. As well as this, keep in mind q is long long integer — 8byte
and Q is unsigned long long
But in the case of int128, the situation is slightly different as there is no 16byte operand for struct.pack()
. Therefore, you should split your number into two int64.
Here's how it should be:
i = 10000000000000000000000000000000000000 # an int128 number
print(len('{0:b}'.format(i)))
max_int64 = 0xFFFFFFFFFFFFFFFF
packed = struct.pack('>qq', (i >> 64) & max_int64, i & max_int64)
a, b = struct.unpack('>QQ', packed)
unpacked = (a << 64)  b
print(unpacked)
print('{0:b}'.format(unpacked))
Out:
123
10000000000000000000000000000000000000
111100001011110111000010000110101011101101001000110110110010000000011110100001101101010000000000000000000000000000000000000
 27,880
 26
 135
 150

1

@hl037_ Thank you for mentioning it. That's a good point. However, I've mentioned about 32bit in the [NOTE] part. Nevertheless, I will update my answer with the cover of int64 and int128 as well. – Benyamin Jafari Apr 01 '22 at 00:05
just use abs for converting unsigned to signed in python
a=12
b=abs(a)
print(b)
Output: 12
 246
 4
 6

I feel like this is only partially true. As the [python MDN](https://docs.python.org/2/library/functions.html) states > `abs()` Return the absolute value of a number. The argument may be a plain or long integer or a floating point number. If the argument is a complex number, its magnitude is returned. **This by definition doesn't return an `unsigned` variable all the time** – Samuel Hulla Aug 17 '18 at 16:53

1

1

1unsigned is very different from abs. Unsigned just changes the way of reading a set of bit values by not considering the first bit to be signed. abs on the other hand changes the signed bit to unset (by taking 2's complement) hence changing the bit representation – Abhishek Agarwal Oct 24 '21 at 18:02